diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc index ba0f33f7d942..8ddfc5e8e33c 100644 --- a/ObsoleteFiles.inc +++ b/ObsoleteFiles.inc @@ -14,6 +14,11 @@ # The file is partitioned: OLD_FILES first, then OLD_LIBS and OLD_DIRS last. # +# 20101101: headers moved to machine/ to x86/ +.if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "i386" +OLD_FILES+=usr/include/machine/apicreg.h +OLD_FILES+=usr/include/machine/mca.h +.endif # 20101020: catch up with vm_page_sleep_if_busy rename OLD_FILES+=usr/share/man/man9/vm_page_sleep_busy.9.gz # 20101011: removed subblock.h from liblzma diff --git a/bin/sh/parser.c b/bin/sh/parser.c index 23db5e73ad38..01907e84e9b2 100644 --- a/bin/sh/parser.c +++ b/bin/sh/parser.c @@ -69,6 +69,11 @@ __FBSDID("$FreeBSD$"); #define EOFMARKLEN 79 #define PROMPTLEN 128 +/* values of checkkwd variable */ +#define CHKALIAS 0x1 +#define CHKKWD 0x2 +#define CHKNL 0x4 + /* values returned by readtoken */ #include "token.h" @@ -102,9 +107,6 @@ static int startlinno; /* line # where last token started */ static int funclinno; /* line # where the current function started */ static struct parser_temp *parser_temp; -/* XXX When 'noaliases' is set to one, no alias expansion takes place. */ -static int noaliases = 0; - static union node *list(int, int); static union node *andor(void); @@ -230,7 +232,7 @@ list(int nlflag, int erflag) union node *ntop, *n1, *n2, *n3; int tok; - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; if (!nlflag && !erflag && tokendlist[peektoken()]) return NULL; ntop = n1 = NULL; @@ -283,7 +285,7 @@ list(int nlflag, int erflag) } else { tokpushback++; } - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; if (!nlflag && !erflag && tokendlist[peektoken()]) return ntop; break; @@ -339,7 +341,7 @@ pipeline(void) int negate, t; negate = 0; - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; TRACE(("pipeline: entered\n")); while (readtoken() == TNOT) negate = !negate; @@ -355,7 +357,7 @@ pipeline(void) do { prev = lp; lp = (struct nodelist *)stalloc(sizeof (struct nodelist)); - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; t = readtoken(); tokpushback++; if (t == TNOT) @@ -388,7 +390,7 @@ command(void) union node *redir, **rpp; int t; - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; redir = NULL; n1 = NULL; rpp = &redir; @@ -429,7 +431,7 @@ command(void) } if (readtoken() != TFI) synexpect(TFI); - checkkwd = 1; + checkkwd = CHKKWD | CHKALIAS; break; case TWHILE: case TUNTIL: { @@ -445,7 +447,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); n1->nbinary.ch2 = list(0, 0); if (readtoken() != TDONE) synexpect(TDONE); - checkkwd = 1; + checkkwd = CHKKWD | CHKALIAS; break; } case TFOR: @@ -487,7 +489,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); if (lasttoken != TNL && lasttoken != TSEMI) tokpushback++; } - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; if ((t = readtoken()) == TDO) t = TDONE; else if (t == TBEGIN) @@ -497,7 +499,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); n1->nfor.body = list(0, 0); if (readtoken() != t) synexpect(t); - checkkwd = 1; + checkkwd = CHKKWD | CHKALIAS; break; case TCASE: n1 = (union node *)stalloc(sizeof (struct ncase)); @@ -513,8 +515,7 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); if (lasttoken != TWORD || ! equal(wordtext, "in")) synerror("expecting \"in\""); cpp = &n1->ncase.cases; - noaliases = 1; /* turn off alias expansion */ - checkkwd = 2, readtoken(); + checkkwd = CHKNL | CHKKWD, readtoken(); while (lasttoken != TESAC) { *cpp = cp = (union node *)stalloc(sizeof (struct nclist)); cp->type = NCLIST; @@ -526,28 +527,28 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); ap->type = NARG; ap->narg.text = wordtext; ap->narg.backquote = backquotelist; - if (checkkwd = 2, readtoken() != TPIPE) + checkkwd = CHKNL | CHKKWD; + if (readtoken() != TPIPE) break; app = &ap->narg.next; readtoken(); } ap->narg.next = NULL; if (lasttoken != TRP) - noaliases = 0, synexpect(TRP); + synexpect(TRP); cp->nclist.body = list(0, 0); - checkkwd = 2; + checkkwd = CHKNL | CHKKWD | CHKALIAS; if ((t = readtoken()) != TESAC) { if (t != TENDCASE) - noaliases = 0, synexpect(TENDCASE); + synexpect(TENDCASE); else - checkkwd = 2, readtoken(); + checkkwd = CHKNL | CHKKWD, readtoken(); } cpp = &cp->nclist.next; } - noaliases = 0; /* reset alias expansion */ *cpp = NULL; - checkkwd = 1; + checkkwd = CHKKWD | CHKALIAS; break; case TLP: n1 = (union node *)stalloc(sizeof (struct nredir)); @@ -556,13 +557,13 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : "")); n1->nredir.redirect = NULL; if (readtoken() != TRP) synexpect(TRP); - checkkwd = 1; + checkkwd = CHKKWD | CHKALIAS; break; case TBEGIN: n1 = list(0, 0); if (readtoken() != TEND) synexpect(TEND); - checkkwd = 1; + checkkwd = CHKKWD | CHKALIAS; break; /* Handle an empty command like other simple commands. */ case TBACKGND: @@ -796,7 +797,6 @@ static int readtoken(void) { int t; - int savecheckkwd = checkkwd; struct alias *ap; #ifdef DEBUG int alreadyseen = tokpushback; @@ -805,25 +805,24 @@ readtoken(void) top: t = xxreadtoken(); - if (checkkwd) { - /* - * eat newlines - */ - if (checkkwd == 2) { - checkkwd = 0; - while (t == TNL) { - parseheredoc(); - t = xxreadtoken(); - } - } else - checkkwd = 0; - /* - * check for keywords and aliases - */ - if (t == TWORD && !quoteflag) - { - const char * const *pp; + /* + * eat newlines + */ + if (checkkwd & CHKNL) { + while (t == TNL) { + parseheredoc(); + t = xxreadtoken(); + } + } + /* + * check for keywords and aliases + */ + if (t == TWORD && !quoteflag) + { + const char * const *pp; + + if (checkkwd & CHKKWD) for (pp = parsekwd; *pp; pp++) { if (**pp == *wordtext && equal(*pp, wordtext)) { @@ -832,16 +831,16 @@ readtoken(void) goto out; } } - if (noaliases == 0 && - (ap = lookupalias(wordtext, 1)) != NULL) { - pushstring(ap->val, strlen(ap->val), ap); - checkkwd = savecheckkwd; - goto top; - } + if (checkkwd & CHKALIAS && + (ap = lookupalias(wordtext, 1)) != NULL) { + pushstring(ap->val, strlen(ap->val), ap); + goto top; } -out: - checkkwd = (t == TNOT) ? savecheckkwd : 0; } +out: + if (t != TNOT) + checkkwd = 0; + #ifdef DEBUG if (!alreadyseen) TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : "")); diff --git a/bin/stty/key.c b/bin/stty/key.c index 413f4d58dfa9..12413019f964 100644 --- a/bin/stty/key.c +++ b/bin/stty/key.c @@ -257,14 +257,15 @@ f_rows(struct info *ip) void f_sane(struct info *ip) { + struct termios def; - ip->t.c_cflag = TTYDEF_CFLAG | (ip->t.c_cflag & CLOCAL); - ip->t.c_iflag = TTYDEF_IFLAG; - ip->t.c_iflag |= ICRNL; + cfmakesane(&def); + ip->t.c_cflag = def.c_cflag | (ip->t.c_cflag & CLOCAL); + ip->t.c_iflag = def.c_iflag; /* preserve user-preference flags in lflag */ #define LKEEP (ECHOKE|ECHOE|ECHOK|ECHOPRT|ECHOCTL|ALTWERASE|TOSTOP|NOFLSH) - ip->t.c_lflag = TTYDEF_LFLAG | (ip->t.c_lflag & LKEEP); - ip->t.c_oflag = TTYDEF_OFLAG; + ip->t.c_lflag = def.c_lflag | (ip->t.c_lflag & LKEEP); + ip->t.c_oflag = def.c_oflag; ip->set = 1; } diff --git a/contrib/gdb/gdb/dwarf2read.c b/contrib/gdb/gdb/dwarf2read.c index 4cfc1fe1b6fe..400750d969be 100644 --- a/contrib/gdb/gdb/dwarf2read.c +++ b/contrib/gdb/gdb/dwarf2read.c @@ -5178,7 +5178,7 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd, line_ptr = dwarf_line_buffer + offset; /* read in the header */ - lh->total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read); + lh->total_length = read_initial_length (abfd, line_ptr, &cu->header, &bytes_read); line_ptr += bytes_read; if (line_ptr + lh->total_length > dwarf_line_buffer + dwarf_line_size) { diff --git a/contrib/gdb/gdb/mipsfbsd-tdep.c b/contrib/gdb/gdb/mipsfbsd-tdep.c index 0be5d2762c4b..06b01668a71d 100644 --- a/contrib/gdb/gdb/mipsfbsd-tdep.c +++ b/contrib/gdb/gdb/mipsfbsd-tdep.c @@ -187,6 +187,14 @@ static struct core_fns mipsfbsd_core_fns = NULL /* next */ }; +static struct core_fns mipsfbsd_elfcore_fns = +{ + bfd_target_elf_flavour, /* core_flavour */ + default_check_format, /* check_format */ + default_core_sniffer, /* core_sniffer */ + fetch_elfcore_registers, /* core_read_registers */ + NULL /* next */ +}; /* * MIPSFBSD Offsets @@ -576,4 +584,6 @@ _initialize_mipsfbsd_tdep (void) { gdbarch_register_osabi (bfd_arch_mips, 0, GDB_OSABI_FREEBSD_ELF, mipsfbsd_init_abi); + add_core_fns (&mipsfbsd_core_fns); + add_core_fns (&mipsfbsd_elfcore_fns); } diff --git a/contrib/top/display.c b/contrib/top/display.c index 94765302dfb2..de91c6cfa45e 100644 --- a/contrib/top/display.c +++ b/contrib/top/display.c @@ -694,7 +694,7 @@ char *text; int width; s = NULL; - width = display_width; + width = screen_width; header_length = strlen(text); if (header_length >= width) { s = malloc((width + 1) * sizeof(char)); @@ -702,6 +702,14 @@ char *text; return (NULL); strncpy(s, text, width); s[width] = '\0'; + } else { + s = malloc((width + 1) * sizeof(char)); + if (s == NULL) + return (NULL); + strncpy(s, text, width); + while (screen_width > header_length) + s[header_length++] = ' '; + s[width] = '\0'; } return (s); } @@ -726,7 +734,7 @@ char *text; if (header_status == ON) { putchar('\n'); - fputs(text, stdout); + standout(text, stdout); lastline++; } else if (header_status == ERASE) diff --git a/contrib/top/top.h b/contrib/top/top.h index a281957c34bd..c51485a558d5 100644 --- a/contrib/top/top.h +++ b/contrib/top/top.h @@ -14,7 +14,7 @@ extern int Header_lines; /* 7 */ /* Maximum number of columns allowed for display */ -#define MAX_COLS 128 +#define MAX_COLS 512 /* Log base 2 of 1024 is 10 (2^10 == 1024) */ #define LOG1024 10 diff --git a/contrib/tzdata/australasia b/contrib/tzdata/australasia index 36a81b0fba24..2c8f7dbfe36c 100644 --- a/contrib/tzdata/australasia +++ b/contrib/tzdata/australasia @@ -1,5 +1,5 @@ #
-# @(#)australasia 8.18 +# @(#)australasia 8.20 # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. @@ -284,13 +284,26 @@ Zone Indian/Cocos 6:27:40 - LMT 1900 # http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html # +# From Alexander Krivenyshev (2010-10-24): +# According to Radio Fiji and Fiji Times online, Fiji will end DST 3 +# weeks earlier than expected - on March 6, 2011, not March 27, 2011... +# Here is confirmation from Government of the Republic of the Fiji Islands, +# Ministry of Information (fiji.gov.fj) web site: +# +# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155 +# +# or +# +# http://www.worldtimezone.com/dst_news/dst_news_fiji04.html +# + # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 S Rule Fiji 1999 2000 - Feb lastSun 3:00 0 - Rule Fiji 2009 only - Nov 29 2:00 1:00 S Rule Fiji 2010 only - Mar lastSun 3:00 0 - Rule Fiji 2010 only - Oct 24 2:00 1:00 S -Rule Fiji 2011 only - Mar lastSun 3:00 0 - +Rule Fiji 2011 only - Mar Sun>=1 3:00 0 - # Zone NAME GMTOFF RULES FORMAT [UNTIL] Zone Pacific/Fiji 11:53:40 - LMT 1915 Oct 26 # Suva 12:00 Fiji FJ%sT # Fiji Time @@ -487,11 +500,21 @@ Zone Pacific/Pago_Pago 12:37:12 - LMT 1879 Jul 5 # http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf # +# From Raymond Hughes (2010-10-07): +# Please see +# +# http://www.mcil.gov.ws +# , +# the Ministry of Commerce, Industry and Labour (sideframe) "Last Sunday +# September 2010 (26/09/10) - adjust clocks forward from 12:00 midnight +# to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks +# backwards from 1:00am to 12:00am" + Zone Pacific/Apia 12:33:04 - LMT 1879 Jul 5 -11:26:56 - LMT 1911 -11:30 - SAMT 1950 # Samoa Time -11:00 - WST 2010 Sep 26 - -11:00 1:00 WSDT 2011 Apr 3 + -11:00 1:00 WSDT 2011 Apr 3 1:00 -11:00 - WST # Solomon Is diff --git a/contrib/wpa/hostapd/.gitignore b/contrib/wpa/hostapd/.gitignore new file mode 100644 index 000000000000..6dd2c2fd35c4 --- /dev/null +++ b/contrib/wpa/hostapd/.gitignore @@ -0,0 +1,7 @@ +*.d +.config +driver_conf.c +hostapd +hostapd_cli +hlr_auc_gw +nt_password_hash diff --git a/contrib/wpa/hostapd/ChangeLog b/contrib/wpa/hostapd/ChangeLog index 18af4b176b9b..a7f1f108f9a0 100644 --- a/contrib/wpa/hostapd/ChangeLog +++ b/contrib/wpa/hostapd/ChangeLog @@ -1,42 +1,108 @@ ChangeLog for hostapd -2010-01-12 - v0.6.10 - * 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] - * fixed WPS selected registrar expiration for internal PIN registrar - * disable PMTU discovery for RADIUS packets - * fixed WPS UPnP SSDP on 32-bit targets - * fixed WPS AP reconfiguration with drivers that do not use hostapd - MLME - * fixed RSN parameter setting for multi-BSS case - * added WPS workarounds for known interoperability issues with broken, - deployed implementation - * update IEEE 802.11w implementation to match with the published - standard - * fixed OpCode when proxying WSC_ACK or WSC_NACK from WPS ER - * fixed proxying of WSC_NACK to WPS ER - * fixed compilation with newer GnuTLS versions - * added support for defining timeout for WPS PINs +2010-09-07 - v0.7.3 + * fixed re-association after WPS not initializing WPA state machine in + some cases + * fixed WPS IE update on reconfiguration + * fixed WPS code not to proxy Probe Request frames for foreign SSIDs + * added WPS workaround for open networks and some known interop issues + * fixed WPS Diffie-Hellman derivation to use correct public key length + * fixed FT RRB messages on big endian CPUs + * changed WPS protection for brute force AP PIN attacks to disable AP + PIN only temporarily (but with increasing time) to avoid usability + issues on Label-only devices + * added wps_ap_pin command for more secure handling of AP PIN + operations (e.g., to generate a random AP PIN and only use it for + short amount of time) + * fixed HT STBC negotiation + +2010-04-18 - v0.7.2 + * fix WPS internal Registrar use when an external Registrar is also + active + * bsd: Cleaned up driver wrapper and added various low-level + configuration options + * 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) + * cleaned up driver wrapper API for multi-BSS operations + * nl80211: fix multi-BSS and VLAN operations + * fix number of issues with IEEE 802.11r/FT; this version is not + backwards compatible with old versions + * add SA Query Request processing in AP mode (IEEE 802.11w) + * fix IGTK PN in group rekeying (IEEE 802.11w) + * fix WPS PBC session overlap detection to use correct attribute + * hostapd_notif_Assoc() can now be called with all IEs to simplify + driver wrappers + * work around interoperability issue with some WPS External Registrar + implementations + * nl80211: fix WPS IE update + * hostapd_cli: add support for action script operations (run a script + on hostapd events) + * fix DH padding with internal crypto code (mainly, for WPS) + * fix WPS association with both WPS IE and WPA/RSN IE present with + driver wrappers that use hostapd MLME (e.g., nl80211) + +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 + * fixed HT Capabilities IE with nl80211 drivers + * moved generic AP functionality code into src/ap + * WPS: handle Selected Registrar as union of info from all Registrars + * remove obsolte Prism54.org driver wrapper + * added internal debugging mechanism with backtrace support and memory + allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y) + * EAP-FAST server: piggyback Phase 2 start with the end of Phase 1 + * WPS: add support for dynamically selecting whether to provision the + PSK as an ASCII passphrase or PSK + * added support for WDS (4-address frame) mode with per-station virtual + interfaces (wds_sta=1 in config file; only supported with + driver=nl80211 for now) * fixed WPS Probe Request processing to handle missing required attribute * fixed PKCS#12 use with OpenSSL 1.0.0 + * detect bridge interface automatically so that bridge parameter in + hostapd.conf becomes optional (though, it may now be used to + automatically add then WLAN interface into a bridge with + driver=nl80211) -2009-03-23 - v0.6.9 - * driver_nl80211: fixed STA accounting data collection (TX/RX bytes - reported correctly; TX/RX packets not yet available from kernel) - * fixed EAPOL/EAP reauthentication when using an external RADIUS - authentication server - * driver_prism54: fixed segmentation fault on initialization - * fixed TNC with EAP-TTLS - * fixed IEEE 802.11r key derivation function to match with the standard - (note: this breaks interoperability with previous version) [Bug 303] - -2009-02-15 - v0.6.8 +2009-11-21 - v0.7.0 * increased hostapd_cli ping interval to 5 seconds and made this configurable with a new command line options (-G) * driver_nl80211: use Linux socket filter to improve performance * added support for external Registrars with WPS (UPnP transport) + * 802.11n: scan for overlapping BSSes before starting 20/40 MHz channel + * driver_nl80211: fixed STA accounting data collection (TX/RX bytes + reported correctly; TX/RX packets not yet available from kernel) + * added support for WPS USBA out-of-band mechanism with USB Flash + Drives (UFD) (CONFIG_WPS_UFD=y) + * fixed EAPOL/EAP reauthentication when using an external RADIUS + authentication server + * fixed TNC with EAP-TTLS + * fixed IEEE 802.11r key derivation function to match with the standard + (note: this breaks interoperability with previous version) [Bug 303] + * 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] + * added number of code size optimizations to remove unnecessary + functionality from the program binary based on build configuration + (part of this automatic; part configurable with CONFIG_NO_* build + options) + * use shared driver wrapper files with wpa_supplicant + * 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 some IEEE 802.11n co-existance rules to disable 40 MHz channels + or modify primary/secondary channels if needed based on neighboring + networks + * added support for NFC out-of-band mechanism with WPS + * added preliminary support for IEEE 802.11r RIC processing 2009-01-06 - v0.6.7 * added support for Wi-Fi Protected Setup (WPS) diff --git a/contrib/wpa/hostapd/Makefile b/contrib/wpa/hostapd/Makefile index 3b3d7feb58c0..6d344d2a92ff 100644 --- a/contrib/wpa/hostapd/Makefile +++ b/contrib/wpa/hostapd/Makefile @@ -6,14 +6,8 @@ ifndef CFLAGS CFLAGS = -MMD -O2 -Wall -g endif -# define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to -# a file (undefine it, if you want to save in binary size) -CFLAGS += -DHOSTAPD_DUMP_STATE - CFLAGS += -I../src -CFLAGS += -I../src/crypto CFLAGS += -I../src/utils -CFLAGS += -I../src/common # Uncomment following line and set the path to your kernel tree include # directory if your C library does not include all header files. @@ -38,12 +32,45 @@ CFLAGS += -DCONFIG_NATIVE_WINDOWS LIBS += -lws2_32 endif -OBJS = hostapd.o ieee802_1x.o eapol_sm.o \ - ieee802_11.o config.o ieee802_11_auth.o accounting.o \ - sta_info.o wpa.o ctrl_iface.o \ - drivers.o preauth.o pmksa_cache.o beacon.o \ - hw_features.o wme.o ap_list.o \ - mlme.o vlan_init.o wpa_auth_ie.o +OBJS += main.o +OBJS += config_file.o + +OBJS += ../src/ap/hostapd.o +OBJS += ../src/ap/wpa_auth_glue.o +OBJS += ../src/ap/drv_callbacks.o +OBJS += ../src/ap/ap_drv_ops.o +OBJS += ../src/ap/utils.o +OBJS += ../src/ap/authsrv.o +OBJS += ../src/ap/ieee802_1x.o +OBJS += ../src/ap/ap_config.o +OBJS += ../src/ap/ieee802_11_auth.o +OBJS += ../src/ap/sta_info.o +OBJS += ../src/ap/wpa_auth.o +OBJS += ../src/ap/tkip_countermeasures.o +OBJS += ../src/ap/ap_mlme.o +OBJS += ../src/ap/wpa_auth_ie.o +OBJS += ../src/ap/preauth_auth.o +OBJS += ../src/ap/pmksa_cache_auth.o + +NEED_RC4=y +NEED_AES=y +NEED_MD5=y +NEED_SHA1=y + +OBJS += ../src/drivers/drivers.o +CFLAGS += -DHOSTAPD + +ifdef CONFIG_WPA_TRACE +CFLAGS += -DWPA_TRACE +OBJS += ../src/utils/trace.o +LDFLAGS += -rdynamic +CFLAGS += -funwind-tables +ifdef CONFIG_WPA_TRACE_BFD +CFLAGS += -DWPA_TRACE_BFD +LIBS += -lbfd +LIBS_c += -lbfd +endif +endif OBJS += ../src/utils/eloop.o OBJS += ../src/utils/common.o @@ -55,24 +82,51 @@ OBJS += ../src/utils/ip_addr.o OBJS += ../src/common/ieee802_11_common.o OBJS += ../src/common/wpa_common.o +OBJS += ../src/eapol_auth/eapol_auth_sm.o + + +ifndef CONFIG_NO_DUMP_STATE +# define HOSTAPD_DUMP_STATE to include SIGUSR1 handler for dumping state to +# a file (undefine it, if you want to save in binary size) +CFLAGS += -DHOSTAPD_DUMP_STATE +OBJS += dump_state.o +OBJS += ../src/eapol_auth/eapol_auth_dump.o +endif + +ifdef CONFIG_NO_RADIUS +CFLAGS += -DCONFIG_NO_RADIUS +CONFIG_NO_ACCOUNTING=y +else OBJS += ../src/radius/radius.o OBJS += ../src/radius/radius_client.o +endif + +ifdef CONFIG_NO_ACCOUNTING +CFLAGS += -DCONFIG_NO_ACCOUNTING +else +OBJS += ../src/ap/accounting.o +endif + +ifdef CONFIG_NO_VLAN +CFLAGS += -DCONFIG_NO_VLAN +else +OBJS += ../src/ap/vlan_init.o +endif + +ifdef CONFIG_NO_CTRL_IFACE +CFLAGS += -DCONFIG_NO_CTRL_IFACE +else +OBJS += ctrl_iface.o +OBJS += ../src/ap/ctrl_iface_ap.o +endif OBJS += ../src/crypto/md5.o -OBJS += ../src/crypto/rc4.o -OBJS += ../src/crypto/md4.o -OBJS += ../src/crypto/sha1.o -OBJS += ../src/crypto/des.o -OBJS += ../src/crypto/aes_wrap.o -OBJS += ../src/crypto/aes.o - -HOBJS=../src/hlr_auc_gw/hlr_auc_gw.o ../src/utils/common.o ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).o ../src/hlr_auc_gw/milenage.o ../src/crypto/aes_wrap.o ../src/crypto/aes.o CFLAGS += -DCONFIG_CTRL_IFACE -DCONFIG_CTRL_IFACE_UNIX ifdef CONFIG_IAPP CFLAGS += -DCONFIG_IAPP -OBJS += iapp.o +OBJS += ../src/ap/iapp.o endif ifdef CONFIG_RSN_PREAUTH @@ -82,78 +136,32 @@ endif ifdef CONFIG_PEERKEY CFLAGS += -DCONFIG_PEERKEY -OBJS += peerkey.o +OBJS += ../src/ap/peerkey_auth.o endif ifdef CONFIG_IEEE80211W CFLAGS += -DCONFIG_IEEE80211W NEED_SHA256=y +NEED_AES_OMAC1=y endif ifdef CONFIG_IEEE80211R CFLAGS += -DCONFIG_IEEE80211R -OBJS += wpa_ft.o +OBJS += ../src/ap/wpa_auth_ft.o NEED_SHA256=y +NEED_AES_OMAC1=y +NEED_AES_UNWRAP=y endif ifdef CONFIG_IEEE80211N CFLAGS += -DCONFIG_IEEE80211N endif -ifdef CONFIG_DRIVER_HOSTAP -CFLAGS += -DCONFIG_DRIVER_HOSTAP -OBJS += driver_hostap.o -endif - -ifdef CONFIG_DRIVER_WIRED -CFLAGS += -DCONFIG_DRIVER_WIRED -OBJS += driver_wired.o -endif - -ifdef CONFIG_DRIVER_MADWIFI -CFLAGS += -DCONFIG_DRIVER_MADWIFI -OBJS += driver_madwifi.o -CONFIG_L2_PACKET=y -endif - -ifdef CONFIG_DRIVER_ATHEROS -CFLAGS += -DCONFIG_DRIVER_ATHEROS -OBJS += driver_atheros.o -CONFIG_L2_PACKET=y -endif - -ifdef CONFIG_DRIVER_PRISM54 -CFLAGS += -DCONFIG_DRIVER_PRISM54 -OBJS += driver_prism54.o -endif - -ifdef CONFIG_DRIVER_NL80211 -CFLAGS += -DCONFIG_DRIVER_NL80211 -OBJS += driver_nl80211.o radiotap.o -LIBS += -lnl -ifdef CONFIG_LIBNL20 -LIBS += -lnl-genl -CFLAGS += -DCONFIG_LIBNL20 -endif -endif - -ifdef CONFIG_DRIVER_BSD -CFLAGS += -DCONFIG_DRIVER_BSD -OBJS += driver_bsd.o -CONFIG_L2_PACKET=y -CONFIG_DNET_PCAP=y -CONFIG_L2_FREEBSD=y -endif - -ifdef CONFIG_DRIVER_TEST -CFLAGS += -DCONFIG_DRIVER_TEST -OBJS += driver_test.o -endif - -ifdef CONFIG_DRIVER_NONE -CFLAGS += -DCONFIG_DRIVER_NONE -OBJS += driver_none.o -endif +include ../src/drivers/drivers.mak +OBJS += $(DRV_AP_OBJS) +CFLAGS += $(DRV_AP_CFLAGS) +LDFLAGS += $(DRV_AP_LDFLAGS) +LIBS += $(DRV_AP_LIBS) ifdef CONFIG_L2_PACKET ifdef CONFIG_DNET_PCAP @@ -173,58 +181,60 @@ endif ifdef CONFIG_EAP_MD5 -CFLAGS += -DEAP_MD5 -OBJS += ../src/eap_server/eap_md5.o +CFLAGS += -DEAP_SERVER_MD5 +OBJS += ../src/eap_server/eap_server_md5.o CHAP=y endif ifdef CONFIG_EAP_TLS -CFLAGS += -DEAP_TLS -OBJS += ../src/eap_server/eap_tls.o +CFLAGS += -DEAP_SERVER_TLS +OBJS += ../src/eap_server/eap_server_tls.o TLS_FUNCS=y endif ifdef CONFIG_EAP_PEAP -CFLAGS += -DEAP_PEAP -OBJS += ../src/eap_server/eap_peap.o +CFLAGS += -DEAP_SERVER_PEAP +OBJS += ../src/eap_server/eap_server_peap.o OBJS += ../src/eap_common/eap_peap_common.o TLS_FUNCS=y CONFIG_EAP_MSCHAPV2=y endif ifdef CONFIG_EAP_TTLS -CFLAGS += -DEAP_TTLS -OBJS += ../src/eap_server/eap_ttls.o +CFLAGS += -DEAP_SERVER_TTLS +OBJS += ../src/eap_server/eap_server_ttls.o TLS_FUNCS=y CHAP=y endif ifdef CONFIG_EAP_MSCHAPV2 -CFLAGS += -DEAP_MSCHAPv2 -OBJS += ../src/eap_server/eap_mschapv2.o +CFLAGS += -DEAP_SERVER_MSCHAPV2 +OBJS += ../src/eap_server/eap_server_mschapv2.o MS_FUNCS=y endif ifdef CONFIG_EAP_GTC -CFLAGS += -DEAP_GTC -OBJS += ../src/eap_server/eap_gtc.o +CFLAGS += -DEAP_SERVER_GTC +OBJS += ../src/eap_server/eap_server_gtc.o endif ifdef CONFIG_EAP_SIM -CFLAGS += -DEAP_SIM -OBJS += ../src/eap_server/eap_sim.o +CFLAGS += -DEAP_SERVER_SIM +OBJS += ../src/eap_server/eap_server_sim.o CONFIG_EAP_SIM_COMMON=y +NEED_AES_CBC=y endif ifdef CONFIG_EAP_AKA -CFLAGS += -DEAP_AKA -OBJS += ../src/eap_server/eap_aka.o +CFLAGS += -DEAP_SERVER_AKA +OBJS += ../src/eap_server/eap_server_aka.o CONFIG_EAP_SIM_COMMON=y NEED_SHA256=y +NEED_AES_CBC=y endif ifdef CONFIG_EAP_AKA_PRIME -CFLAGS += -DEAP_AKA_PRIME +CFLAGS += -DEAP_SERVER_AKA_PRIME endif ifdef CONFIG_EAP_SIM_COMMON @@ -237,47 +247,52 @@ NEED_FIPS186_2_PRF=y endif ifdef CONFIG_EAP_PAX -CFLAGS += -DEAP_PAX -OBJS += ../src/eap_server/eap_pax.o ../src/eap_common/eap_pax_common.o +CFLAGS += -DEAP_SERVER_PAX +OBJS += ../src/eap_server/eap_server_pax.o ../src/eap_common/eap_pax_common.o endif ifdef CONFIG_EAP_PSK -CFLAGS += -DEAP_PSK -OBJS += ../src/eap_server/eap_psk.o ../src/eap_common/eap_psk_common.o +CFLAGS += -DEAP_SERVER_PSK +OBJS += ../src/eap_server/eap_server_psk.o ../src/eap_common/eap_psk_common.o +NEED_AES_OMAC1=y +NEED_AES_ENCBLOCK=y +NEED_AES_EAX=y endif ifdef CONFIG_EAP_SAKE -CFLAGS += -DEAP_SAKE -OBJS += ../src/eap_server/eap_sake.o ../src/eap_common/eap_sake_common.o +CFLAGS += -DEAP_SERVER_SAKE +OBJS += ../src/eap_server/eap_server_sake.o ../src/eap_common/eap_sake_common.o endif ifdef CONFIG_EAP_GPSK -CFLAGS += -DEAP_GPSK -OBJS += ../src/eap_server/eap_gpsk.o ../src/eap_common/eap_gpsk_common.o +CFLAGS += -DEAP_SERVER_GPSK +OBJS += ../src/eap_server/eap_server_gpsk.o ../src/eap_common/eap_gpsk_common.o ifdef CONFIG_EAP_GPSK_SHA256 -CFLAGS += -DEAP_GPSK_SHA256 +CFLAGS += -DEAP_SERVER_GPSK_SHA256 endif NEED_SHA256=y +NEED_AES_OMAC1=y endif ifdef CONFIG_EAP_VENDOR_TEST -CFLAGS += -DEAP_VENDOR_TEST -OBJS += ../src/eap_server/eap_vendor_test.o +CFLAGS += -DEAP_SERVER_VENDOR_TEST +OBJS += ../src/eap_server/eap_server_vendor_test.o endif ifdef CONFIG_EAP_FAST -CFLAGS += -DEAP_FAST -OBJS += ../src/eap_server/eap_fast.o +CFLAGS += -DEAP_SERVER_FAST +OBJS += ../src/eap_server/eap_server_fast.o OBJS += ../src/eap_common/eap_fast_common.o TLS_FUNCS=y NEED_T_PRF=y +NEED_AES_UNWRAP=y endif ifdef CONFIG_WPS -CFLAGS += -DCONFIG_WPS -DEAP_WSC +CFLAGS += -DCONFIG_WPS -DEAP_SERVER_WSC OBJS += ../src/utils/uuid.o -OBJS += wps_hostapd.o -OBJS += ../src/eap_server/eap_wsc.o ../src/eap_common/eap_wsc_common.o +OBJS += ../src/ap/wps_hostapd.o +OBJS += ../src/eap_server/eap_server_wsc.o ../src/eap_common/eap_wsc_common.o OBJS += ../src/wps/wps.o OBJS += ../src/wps/wps_common.o OBJS += ../src/wps/wps_attr_parse.o @@ -288,8 +303,35 @@ OBJS += ../src/wps/wps_enrollee.o OBJS += ../src/wps/wps_registrar.o NEED_DH_GROUPS=y NEED_SHA256=y -NEED_CRYPTO=y NEED_BASE64=y +NEED_AES_CBC=y +NEED_MODEXP=y +CONFIG_EAP=y + +ifdef CONFIG_WPS_UFD +CFLAGS += -DCONFIG_WPS_UFD +OBJS += ../src/wps/wps_ufd.o +NEED_WPS_OOB=y +endif + +ifdef CONFIG_WPS_NFC +CFLAGS += -DCONFIG_WPS_NFC +OBJS += ../src/wps/ndef.o +OBJS += ../src/wps/wps_nfc.o +NEED_WPS_OOB=y +ifdef CONFIG_WPS_NFC_PN531 +PN531_PATH ?= /usr/local/src/nfc +CFLAGS += -DCONFIG_WPS_NFC_PN531 +CFLAGS += -I${PN531_PATH}/inc +OBJS += ../src/wps/wps_nfc_pn531.o +LIBS += ${PN531_PATH}/lib/wpsnfc.dll +LIBS += ${PN531_PATH}/lib/libnfc_mapping_pn53x.dll +endif +endif + +ifdef NEED_WPS_OOB +CFLAGS += -DCONFIG_WPS_OOB +endif ifdef CONFIG_WPS_UPNP CFLAGS += -DCONFIG_WPS_UPNP @@ -297,22 +339,28 @@ OBJS += ../src/wps/wps_upnp.o OBJS += ../src/wps/wps_upnp_ssdp.o OBJS += ../src/wps/wps_upnp_web.o OBJS += ../src/wps/wps_upnp_event.o +OBJS += ../src/wps/wps_upnp_ap.o +OBJS += ../src/wps/upnp_xml.o OBJS += ../src/wps/httpread.o +OBJS += ../src/wps/http_client.o +OBJS += ../src/wps/http_server.o endif endif ifdef CONFIG_EAP_IKEV2 -CFLAGS += -DEAP_IKEV2 -OBJS += ../src/eap_server/eap_ikev2.o ../src/eap_server/ikev2.o +CFLAGS += -DEAP_SERVER_IKEV2 +OBJS += ../src/eap_server/eap_server_ikev2.o ../src/eap_server/ikev2.o OBJS += ../src/eap_common/eap_ikev2_common.o ../src/eap_common/ikev2_common.o NEED_DH_GROUPS=y NEED_DH_GROUPS_ALL=y +NEED_MODEXP=y +NEED_CIPHER=y endif ifdef CONFIG_EAP_TNC -CFLAGS += -DEAP_TNC -OBJS += ../src/eap_server/eap_tnc.o +CFLAGS += -DEAP_SERVER_TNC +OBJS += ../src/eap_server/eap_server_tnc.o OBJS += ../src/eap_server/tncs.o NEED_BASE64=y ifndef CONFIG_DRIVER_BSD @@ -321,135 +369,150 @@ endif endif # Basic EAP functionality is needed for EAPOL -OBJS += ../src/eap_server/eap.o +OBJS += eap_register.o +OBJS += ../src/eap_server/eap_server.o OBJS += ../src/eap_common/eap_common.o -OBJS += ../src/eap_server/eap_methods.o -OBJS += ../src/eap_server/eap_identity.o +OBJS += ../src/eap_server/eap_server_methods.o +OBJS += ../src/eap_server/eap_server_identity.o +CFLAGS += -DEAP_SERVER_IDENTITY ifdef CONFIG_EAP CFLAGS += -DEAP_SERVER endif -ifndef CONFIG_TLS -CONFIG_TLS=openssl -endif - -ifeq ($(CONFIG_TLS), internal) -ifndef CONFIG_CRYPTO -CONFIG_CRYPTO=internal -endif -endif -ifeq ($(CONFIG_CRYPTO), libtomcrypt) -CFLAGS += -DCONFIG_INTERNAL_X509 -endif -ifeq ($(CONFIG_CRYPTO), internal) -CFLAGS += -DCONFIG_INTERNAL_X509 -endif - - -ifdef TLS_FUNCS -# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS) -CFLAGS += -DEAP_TLS_FUNCS -OBJS += ../src/eap_server/eap_tls_common.o -NEED_TLS_PRF=y -ifeq ($(CONFIG_TLS), openssl) -OBJS += ../src/crypto/tls_openssl.o -LIBS += -lssl -lcrypto -LIBS_p += -lcrypto -LIBS_h += -lcrypto -endif -ifeq ($(CONFIG_TLS), gnutls) -OBJS += ../src/crypto/tls_gnutls.o -LIBS += -lgnutls -lgcrypt -lgpg-error -LIBS_p += -lgcrypt -LIBS_h += -lgcrypt -endif -ifdef CONFIG_GNUTLS_EXTRA -CFLAGS += -DCONFIG_GNUTLS_EXTRA -LIBS += -lgnutls-extra -endif -ifeq ($(CONFIG_TLS), internal) -OBJS += ../src/crypto/tls_internal.o -OBJS += ../src/tls/tlsv1_common.o ../src/tls/tlsv1_record.o -OBJS += ../src/tls/tlsv1_cred.o ../src/tls/tlsv1_server.o -OBJS += ../src/tls/tlsv1_server_write.o ../src/tls/tlsv1_server_read.o -OBJS += ../src/tls/asn1.o ../src/tls/x509v3.o -OBJS_p += ../src/tls/asn1.o -OBJS_p += ../src/crypto/rc4.o ../src/crypto/aes_wrap.o ../src/crypto/aes.o -NEED_BASE64=y -CFLAGS += -DCONFIG_TLS_INTERNAL -CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER -ifeq ($(CONFIG_CRYPTO), internal) -ifdef CONFIG_INTERNAL_LIBTOMMATH -CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH -else -LIBS += -ltommath -LIBS_p += -ltommath -endif -endif -ifeq ($(CONFIG_CRYPTO), libtomcrypt) -LIBS += -ltomcrypt -ltfm -LIBS_p += -ltomcrypt -ltfm -endif -endif -NEED_CRYPTO=y -else -OBJS += ../src/crypto/tls_none.o -endif - ifdef CONFIG_PKCS12 CFLAGS += -DPKCS12_FUNCS endif ifdef MS_FUNCS OBJS += ../src/crypto/ms_funcs.o -NEED_CRYPTO=y +NEED_DES=y +NEED_MD4=y endif ifdef CHAP OBJS += ../src/eap_common/chap.o endif -ifdef NEED_CRYPTO -ifndef TLS_FUNCS +ifdef TLS_FUNCS +NEED_DES=y +# Shared TLS functions (needed for EAP_TLS, EAP_PEAP, and EAP_TTLS) +CFLAGS += -DEAP_TLS_FUNCS +OBJS += ../src/eap_server/eap_server_tls_common.o +NEED_TLS_PRF=y +endif + +ifndef CONFIG_TLS +CONFIG_TLS=openssl +endif + ifeq ($(CONFIG_TLS), openssl) +ifdef TLS_FUNCS +OBJS += ../src/crypto/tls_openssl.o +LIBS += -lssl +endif +OBJS += ../src/crypto/crypto_openssl.o +HOBJS += ../src/crypto/crypto_openssl.o +ifdef NEED_FIPS186_2_PRF +OBJS += ../src/crypto/fips_prf_openssl.o +endif LIBS += -lcrypto -LIBS_p += -lcrypto LIBS_h += -lcrypto endif + ifeq ($(CONFIG_TLS), gnutls) -LIBS += -lgcrypt -LIBS_p += -lgcrypt -LIBS_h += -lgcrypt -endif -ifeq ($(CONFIG_TLS), internal) -ifeq ($(CONFIG_CRYPTO), libtomcrypt) -LIBS += -ltomcrypt -ltfm -LIBS_p += -ltomcrypt -ltfm +ifdef TLS_FUNCS +OBJS += ../src/crypto/tls_gnutls.o +LIBS += -lgnutls -lgpg-error +ifdef CONFIG_GNUTLS_EXTRA +CFLAGS += -DCONFIG_GNUTLS_EXTRA +LIBS += -lgnutls-extra endif endif -endif -ifeq ($(CONFIG_TLS), openssl) -OBJS += ../src/crypto/crypto_openssl.o -OBJS_p += ../src/crypto/crypto_openssl.o -HOBJS += ../src/crypto/crypto_openssl.o -CONFIG_INTERNAL_SHA256=y -endif -ifeq ($(CONFIG_TLS), gnutls) OBJS += ../src/crypto/crypto_gnutls.o -OBJS_p += ../src/crypto/crypto_gnutls.o HOBJS += ../src/crypto/crypto_gnutls.o -CONFIG_INTERNAL_SHA256=y +ifdef NEED_FIPS186_2_PRF +OBJS += ../src/crypto/fips_prf_gnutls.o endif +LIBS += -lgcrypt +LIBS_h += -lgcrypt +CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_RC4=y +CONFIG_INTERNAL_DH_GROUP5=y +endif + +ifeq ($(CONFIG_TLS), schannel) +ifdef TLS_FUNCS +OBJS += ../src/crypto/tls_schannel.o +endif +OBJS += ../src/crypto/crypto_cryptoapi.o +OBJS_p += ../src/crypto/crypto_cryptoapi.o +CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_RC4=y +CONFIG_INTERNAL_DH_GROUP5=y +endif + +ifeq ($(CONFIG_TLS), nss) +ifdef TLS_FUNCS +OBJS += ../src/crypto/tls_nss.o +LIBS += -lssl3 +endif +OBJS += ../src/crypto/crypto_nss.o +ifdef NEED_FIPS186_2_PRF +OBJS += ../src/crypto/fips_prf_nss.o +endif +LIBS += -lnss3 +LIBS_h += -lnss3 +CONFIG_INTERNAL_MD4=y +CONFIG_INTERNAL_DH_GROUP5=y +endif + ifeq ($(CONFIG_TLS), internal) +ifndef CONFIG_CRYPTO +CONFIG_CRYPTO=internal +endif +ifdef TLS_FUNCS +OBJS += ../src/crypto/crypto_internal-rsa.o +OBJS += ../src/crypto/tls_internal.o +OBJS += ../src/tls/tlsv1_common.o +OBJS += ../src/tls/tlsv1_record.o +OBJS += ../src/tls/tlsv1_cred.o +OBJS += ../src/tls/tlsv1_server.o +OBJS += ../src/tls/tlsv1_server_write.o +OBJS += ../src/tls/tlsv1_server_read.o +OBJS += ../src/tls/asn1.o +OBJS += ../src/tls/rsa.o +OBJS += ../src/tls/x509v3.o +OBJS += ../src/tls/pkcs1.o +OBJS += ../src/tls/pkcs5.o +OBJS += ../src/tls/pkcs8.o +NEED_SHA256=y +NEED_BASE64=y +NEED_TLS_PRF=y +NEED_MODEXP=y +NEED_CIPHER=y +CFLAGS += -DCONFIG_TLS_INTERNAL +CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER +endif +ifdef NEED_CIPHER +NEED_DES=y +OBJS += ../src/crypto/crypto_internal-cipher.o +endif +ifdef NEED_MODEXP +OBJS += ../src/crypto/crypto_internal-modexp.o +OBJS += ../src/tls/bignum.o +endif ifeq ($(CONFIG_CRYPTO), libtomcrypt) OBJS += ../src/crypto/crypto_libtomcrypt.o -OBJS_p += ../src/crypto/crypto_libtomcrypt.o +LIBS += -ltomcrypt -ltfm +LIBS_h += -ltomcrypt -ltfm CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_RC4=y +CONFIG_INTERNAL_DH_GROUP5=y endif ifeq ($(CONFIG_CRYPTO), internal) -OBJS += ../src/crypto/crypto_internal.o ../src/tls/rsa.o ../src/tls/bignum.o -OBJS_p += ../src/crypto/crypto_internal.o ../src/tls/rsa.o ../src/tls/bignum.o +OBJS += ../src/crypto/crypto_internal.o +NEED_AES_DEC=y CFLAGS += -DCONFIG_CRYPTO_INTERNAL ifdef CONFIG_INTERNAL_LIBTOMMATH CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH @@ -458,7 +521,7 @@ CFLAGS += -DLTM_FAST endif else LIBS += -ltommath -LIBS_p += -ltommath +LIBS_h += -ltommath endif CONFIG_INTERNAL_AES=y CONFIG_INTERNAL_DES=y @@ -466,55 +529,140 @@ CONFIG_INTERNAL_SHA1=y CONFIG_INTERNAL_MD4=y CONFIG_INTERNAL_MD5=y CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_RC4=y +CONFIG_INTERNAL_DH_GROUP5=y +endif +ifeq ($(CONFIG_CRYPTO), cryptoapi) +OBJS += ../src/crypto/crypto_cryptoapi.o +OBJS_p += ../src/crypto/crypto_cryptoapi.o +CFLAGS += -DCONFIG_CRYPTO_CRYPTOAPI +CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_RC4=y endif endif -else + +ifeq ($(CONFIG_TLS), none) +ifdef TLS_FUNCS +OBJS += ../src/crypto/tls_none.o +CFLAGS += -DEAP_TLS_NONE CONFIG_INTERNAL_AES=y CONFIG_INTERNAL_SHA1=y CONFIG_INTERNAL_MD5=y +endif +OBJS += ../src/crypto/crypto_none.o +OBJS_p += ../src/crypto/crypto_none.o CONFIG_INTERNAL_SHA256=y +CONFIG_INTERNAL_RC4=y endif +ifndef TLS_FUNCS +OBJS += ../src/crypto/tls_none.o +ifeq ($(CONFIG_TLS), internal) +CONFIG_INTERNAL_AES=y +CONFIG_INTERNAL_SHA1=y +CONFIG_INTERNAL_MD5=y +CONFIG_INTERNAL_RC4=y +endif +endif + +AESOBJS = # none so far ifdef CONFIG_INTERNAL_AES -CFLAGS += -DINTERNAL_AES +AESOBJS += ../src/crypto/aes-internal.o ../src/crypto/aes-internal-enc.o endif + +AESOBJS += ../src/crypto/aes-wrap.o +ifdef NEED_AES_EAX +AESOBJS += ../src/crypto/aes-eax.o +NEED_AES_CTR=y +endif +ifdef NEED_AES_CTR +AESOBJS += ../src/crypto/aes-ctr.o +endif +ifdef NEED_AES_ENCBLOCK +AESOBJS += ../src/crypto/aes-encblock.o +endif +ifdef NEED_AES_OMAC1 +AESOBJS += ../src/crypto/aes-omac1.o +endif +ifdef NEED_AES_UNWRAP +NEED_AES_DEC=y +AESOBJS += ../src/crypto/aes-unwrap.o +endif +ifdef NEED_AES_CBC +NEED_AES_DEC=y +AESOBJS += ../src/crypto/aes-cbc.o +endif +ifdef NEED_AES_DEC +ifdef CONFIG_INTERNAL_AES +AESOBJS += ../src/crypto/aes-internal-dec.o +endif +endif +ifdef NEED_AES +OBJS += $(AESOBJS) +endif + +ifdef NEED_SHA1 +SHA1OBJS += ../src/crypto/sha1.o ifdef CONFIG_INTERNAL_SHA1 -CFLAGS += -DINTERNAL_SHA1 +SHA1OBJS += ../src/crypto/sha1-internal.o +ifdef NEED_FIPS186_2_PRF +SHA1OBJS += ../src/crypto/fips_prf_internal.o endif -ifdef CONFIG_INTERNAL_SHA256 -CFLAGS += -DINTERNAL_SHA256 endif +SHA1OBJS += ../src/crypto/sha1-pbkdf2.o +ifdef NEED_T_PRF +SHA1OBJS += ../src/crypto/sha1-tprf.o +endif +ifdef NEED_TLS_PRF +SHA1OBJS += ../src/crypto/sha1-tlsprf.o +endif +endif + +ifdef NEED_SHA1 +OBJS += $(SHA1OBJS) +endif + +ifdef NEED_MD5 ifdef CONFIG_INTERNAL_MD5 -CFLAGS += -DINTERNAL_MD5 +OBJS += ../src/crypto/md5-internal.o endif +endif + +ifdef NEED_MD4 ifdef CONFIG_INTERNAL_MD4 -CFLAGS += -DINTERNAL_MD4 +OBJS += ../src/crypto/md4-internal.o endif +endif + +ifdef NEED_DES ifdef CONFIG_INTERNAL_DES -CFLAGS += -DINTERNAL_DES +OBJS += ../src/crypto/des-internal.o +endif +endif + +ifdef NEED_RC4 +ifdef CONFIG_INTERNAL_RC4 +OBJS += ../src/crypto/rc4.o +endif endif ifdef NEED_SHA256 OBJS += ../src/crypto/sha256.o +ifdef CONFIG_INTERNAL_SHA256 +OBJS += ../src/crypto/sha256-internal.o +endif endif ifdef NEED_DH_GROUPS OBJS += ../src/crypto/dh_groups.o +endif ifdef NEED_DH_GROUPS_ALL CFLAGS += -DALL_DH_GROUPS endif +ifdef CONFIG_INTERNAL_DH_GROUP5 +ifdef NEED_DH_GROUPS +OBJS += ../src/crypto/dh_group5.o endif - -ifndef NEED_FIPS186_2_PRF -CFLAGS += -DCONFIG_NO_FIPS186_2_PRF -endif - -ifndef NEED_T_PRF -CFLAGS += -DCONFIG_NO_T_PRF -endif - -ifndef NEED_TLS_PRF -CFLAGS += -DCONFIG_NO_TLS_PRF endif ifdef CONFIG_RADIUS_SERVER @@ -540,16 +688,20 @@ ifdef NEED_BASE64 OBJS += ../src/utils/base64.o endif -ifdef CONFIG_NO_STDOUT_DEBUG -CFLAGS += -DCONFIG_NO_STDOUT_DEBUG +ifdef NEED_AP_MLME +OBJS += ../src/ap/beacon.o +OBJS += ../src/ap/wmm.o +OBJS += ../src/ap/ap_list.o +OBJS += ../src/ap/ieee802_11.o +OBJS += ../src/ap/hw_features.o +CFLAGS += -DNEED_AP_MLME +endif +ifdef CONFIG_IEEE80211N +OBJS += ../src/ap/ieee802_11_ht.o endif -ifdef CONFIG_NO_AES_EXTRAS -CFLAGS += -DCONFIG_NO_AES_UNWRAP -CFLAGS += -DCONFIG_NO_AES_CTR -DCONFIG_NO_AES_OMAC1 -CFLAGS += -DCONFIG_NO_AES_EAX -DCONFIG_NO_AES_CBC -CFLAGS += -DCONFIG_NO_AES_DECRYPT -CFLAGS += -DCONFIG_NO_AES_ENCRYPT_BLOCK +ifdef CONFIG_NO_STDOUT_DEBUG +CFLAGS += -DCONFIG_NO_STDOUT_DEBUG endif ALL=hostapd hostapd_cli @@ -577,59 +729,63 @@ verify_config: fi install: all - for i in $(ALL); do cp $$i /usr/local/bin/$$i; done + for i in $(ALL); do cp -f $$i /usr/local/bin/$$i; done -hostapd: $(OBJS) - $(CC) -o hostapd $(OBJS) $(LIBS) +../src/drivers/build.hostapd: + @if [ -f ../src/drivers/build.wpa_supplicant ]; then \ + $(MAKE) -C ../src/drivers clean; \ + fi + @touch ../src/drivers/build.hostapd + +BCHECK=../src/drivers/build.hostapd + +hostapd: $(BCHECK) $(OBJS) + $(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS) OBJS_c = hostapd_cli.o ../src/common/wpa_ctrl.o ../src/utils/os_$(CONFIG_OS).o +ifdef CONFIG_WPA_TRACE +OBJS_c += ../src/utils/trace.o +OBJS_c += ../src/utils/wpa_debug.o +endif hostapd_cli: $(OBJS_c) - $(CC) -o hostapd_cli $(OBJS_c) + $(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c) -NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o ../src/crypto/sha1.o ../src/crypto/rc4.o ../src/crypto/md5.o +NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) ../src/crypto/md5.o +ifdef NEED_RC4 +ifdef CONFIG_INTERNAL_RC4 +NOBJS += ../src/crypto/rc4.o +endif +endif +ifdef CONFIG_INTERNAL_MD5 +NOBJS += ../src/crypto/md5-internal.o +endif NOBJS += ../src/crypto/crypto_openssl.o ../src/utils/os_$(CONFIG_OS).o +NOBJS += ../src/utils/wpa_debug.o +NOBJS += ../src/utils/wpabuf.o +ifdef CONFIG_WPA_TRACE +NOBJS += ../src/utils/trace.o +LIBS_n += -lbfd +endif ifdef TLS_FUNCS LIBS_n += -lcrypto endif +HOBJS += hlr_auc_gw.o ../src/utils/common.o ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).o ../src/utils/wpabuf.o ../src/crypto/milenage.o +HOBJS += ../src/crypto/aes-encblock.o +ifdef CONFIG_INTERNAL_AES +HOBJS += ../src/crypto/aes-internal.o +HOBJS += ../src/crypto/aes-internal-enc.o +endif + nt_password_hash: $(NOBJS) - $(CC) -o nt_password_hash $(NOBJS) $(LIBS_n) + $(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n) hlr_auc_gw: $(HOBJS) - $(CC) -o hlr_auc_gw $(HOBJS) $(LIBS_h) + $(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h) clean: $(MAKE) -C ../src clean rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw rm -f *.d -%.eps: %.fig - fig2dev -L eps $*.fig $*.eps - -%.png: %.fig - fig2dev -L png -m 3 $*.fig | pngtopnm | pnmscale 0.4 | pnmtopng \ - > $*.png - -docs-pics: doc/hostapd.png doc/hostapd.eps - -docs: docs-pics - (cd ..; doxygen hostapd/doc/doxygen.full; cd hostapd) - $(MAKE) -C doc/latex - cp doc/latex/refman.pdf hostapd-devel.pdf - -docs-fast: docs-pics - (cd ..; doxygen hostapd/doc/doxygen.fast; cd hostapd) - -clean-docs: - rm -rf doc/latex doc/html - rm -f doc/hostapd.{eps,png} hostapd-devel.pdf - -TEST_SRC_MILENAGE = ../src/hlr_auc_gw/milenage.c ../src/crypto/aes_wrap.c ../src/crypto/aes.c ../src/utils/common.c ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).c -test-milenage: $(TEST_SRC_MILENAGE) - $(CC) -o test-milenage -Wall -Werror $(TEST_SRC_MILENAGE) \ - -DTEST_MAIN_MILENAGE -I. -DINTERNAL_AES \ - -I../src/crypto -I../src/utils - ./test-milenage - rm test-milenage - -include $(OBJS:%.o=%.d) diff --git a/contrib/wpa/hostapd/README b/contrib/wpa/hostapd/README index eb9aa4815b4f..1af487d76593 100644 --- a/contrib/wpa/hostapd/README +++ b/contrib/wpa/hostapd/README @@ -2,7 +2,7 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP Authenticator and RADIUS authentication server ================================================================ -Copyright (c) 2002-2009, Jouni Malinen and contributors +Copyright (c) 2002-2010, Jouni Malinen and contributors All Rights Reserved. This program is dual-licensed under both the GPL version 2 and BSD @@ -95,9 +95,6 @@ Current hardware/software requirements: madwifi driver root directory in .config (see defconfig file for an example: CFLAGS += -I ) - Prism54 driver for Intersil/Conexant Prism GT/Duette/Indigo - (http://www.prism54.org/) - mac80211-based drivers that support AP mode (with driver=nl80211). This includes drivers for Atheros (ath9k) and Broadcom (b43) chipsets. diff --git a/contrib/wpa/hostapd/README-WPS b/contrib/wpa/hostapd/README-WPS index e0e370b5bc8f..74f211348ede 100644 --- a/contrib/wpa/hostapd/README-WPS +++ b/contrib/wpa/hostapd/README-WPS @@ -62,7 +62,6 @@ includes WPS support and uses madwifi driver interface: CONFIG_DRIVER_MADWIFI=y CFLAGS += -I/usr/src/madwifi-0.9.3 -CONFIG_EAP=y CONFIG_WPS=y CONFIG_WPS_UPNP=y @@ -196,6 +195,33 @@ which will generate a new WPA PSK in the same way as the PIN method described above. +When an external Registrar is used, the AP can act as an Enrollee and +use its AP PIN. A static AP PIN (e.g., one one a label in the AP +device) can be configured in hostapd.conf (ap_pin parameter). A more +secure option is to use hostapd_cli wps_ap_pin command to enable the +AP PIN only based on user action (and even better security by using a +random AP PIN for each session, i.e., by using "wps_ap_pin random" +command with a timeout value). Following commands are available for +managing the dynamic AP PIN operations: + +hostapd_cli wps_ap_pin disable +- disable AP PIN (i.e., do not allow external Registrars to use it to + learn the current AP settings or to reconfigure the AP) + +hostapd_cli wps_ap_pin random [timeout] +- generate a random AP PIN and enable it +- if the optional timeout parameter is given, the AP PIN will be enabled + for the specified number of seconds + +hostapd_cli wps_ap_pin get +- fetch the current AP PIN + +hostapd_cli wps_ap_pin set [timeout] +- set the AP PIN and enable it +- if the optional timeout parameter is given, the AP PIN will be enabled + for the specified number of seconds + + Credential generation and configuration changes ----------------------------------------------- diff --git a/contrib/wpa/hostapd/config.c b/contrib/wpa/hostapd/config_file.c similarity index 78% rename from contrib/wpa/hostapd/config.c rename to contrib/wpa/hostapd/config_file.c index 692b1a412e02..8916b03db826 100644 --- a/contrib/wpa/hostapd/config.c +++ b/contrib/wpa/hostapd/config_file.c @@ -1,7 +1,6 @@ /* - * hostapd / Configuration file - * Copyright (c) 2003-2008, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation + * hostapd / Configuration file parser + * Copyright (c) 2003-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,27 +12,26 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" #ifndef CONFIG_NATIVE_WINDOWS #include #endif /* CONFIG_NATIVE_WINDOWS */ -#include "hostapd.h" -#include "driver.h" -#include "sha1.h" +#include "utils/common.h" +#include "utils/uuid.h" +#include "common/ieee802_11_defs.h" +#include "drivers/driver.h" #include "eap_server/eap.h" #include "radius/radius_client.h" -#include "wpa_common.h" -#include "wpa.h" -#include "uuid.h" -#include "eap_common/eap_wsc_common.h" +#include "ap/wpa_auth.h" +#include "ap/ap_config.h" +#include "config_file.h" -#define MAX_STA_COUNT 2007 - -extern struct wpa_driver_ops *hostapd_drivers[]; +extern struct wpa_driver_ops *wpa_drivers[]; +#ifndef CONFIG_NO_VLAN static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss, const char *fname) { @@ -113,168 +111,7 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss, return 0; } - - -static void hostapd_config_free_vlan(struct hostapd_bss_config *bss) -{ - struct hostapd_vlan *vlan, *prev; - - vlan = bss->vlan; - prev = NULL; - while (vlan) { - prev = vlan; - vlan = vlan->next; - os_free(prev); - } - - bss->vlan = NULL; -} - - -/* convert floats with one decimal place to value*10 int, i.e., - * "1.5" will return 15 */ -static int hostapd_config_read_int10(const char *value) -{ - int i, d; - char *pos; - - i = atoi(value); - pos = os_strchr(value, '.'); - d = 0; - if (pos) { - pos++; - if (*pos >= '0' && *pos <= '9') - d = *pos - '0'; - } - - return i * 10 + d; -} - - -static void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) -{ - bss->logger_syslog_level = HOSTAPD_LEVEL_INFO; - bss->logger_stdout_level = HOSTAPD_LEVEL_INFO; - bss->logger_syslog = (unsigned int) -1; - bss->logger_stdout = (unsigned int) -1; - - bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED; - - bss->wep_rekeying_period = 300; - /* use key0 in individual key and key1 in broadcast key */ - bss->broadcast_key_idx_min = 1; - bss->broadcast_key_idx_max = 2; - bss->eap_reauth_period = 3600; - - bss->wpa_group_rekey = 600; - bss->wpa_gmk_rekey = 86400; - bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; - bss->wpa_pairwise = WPA_CIPHER_TKIP; - bss->wpa_group = WPA_CIPHER_TKIP; - bss->rsn_pairwise = 0; - - bss->max_num_sta = MAX_STA_COUNT; - - bss->dtim_period = 2; - - bss->radius_server_auth_port = 1812; - bss->ap_max_inactivity = AP_MAX_INACTIVITY; - bss->eapol_version = EAPOL_VERSION; - - bss->max_listen_interval = 65535; - -#ifdef CONFIG_IEEE80211W - bss->assoc_sa_query_max_timeout = 1000; - bss->assoc_sa_query_retry_timeout = 201; -#endif /* CONFIG_IEEE80211W */ -#ifdef EAP_FAST - /* both anonymous and authenticated provisioning */ - bss->eap_fast_prov = 3; - bss->pac_key_lifetime = 7 * 24 * 60 * 60; - bss->pac_key_refresh_time = 1 * 24 * 60 * 60; -#endif /* EAP_FAST */ -} - - -static struct hostapd_config * hostapd_config_defaults(void) -{ - struct hostapd_config *conf; - struct hostapd_bss_config *bss; - int i; - const int aCWmin = 4, aCWmax = 10; - const struct hostapd_wmm_ac_params ac_bk = - { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */ - const struct hostapd_wmm_ac_params ac_be = - { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ - const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ - { aCWmin - 1, aCWmin, 2, 3000 / 32, 1 }; - const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ - { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 }; - - conf = os_zalloc(sizeof(*conf)); - bss = os_zalloc(sizeof(*bss)); - if (conf == NULL || bss == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate memory for " - "configuration data."); - os_free(conf); - os_free(bss); - return NULL; - } - - /* set default driver based on configuration */ - conf->driver = hostapd_drivers[0]; - if (conf->driver == NULL) { - wpa_printf(MSG_ERROR, "No driver wrappers registered!"); - os_free(conf); - os_free(bss); - return NULL; - } - - bss->radius = os_zalloc(sizeof(*bss->radius)); - if (bss->radius == NULL) { - os_free(conf); - os_free(bss); - return NULL; - } - - hostapd_config_defaults_bss(bss); - - conf->num_bss = 1; - conf->bss = bss; - - conf->beacon_int = 100; - conf->rts_threshold = -1; /* use driver default: 2347 */ - conf->fragm_threshold = -1; /* user driver default: 2346 */ - conf->send_probe_response = 1; - conf->bridge_packets = INTERNAL_BRIDGE_DO_NOT_CONTROL; - - for (i = 0; i < NUM_TX_QUEUES; i++) - conf->tx_queue[i].aifs = -1; /* use hw default */ - - conf->wmm_ac_params[0] = ac_be; - conf->wmm_ac_params[1] = ac_bk; - conf->wmm_ac_params[2] = ac_vi; - conf->wmm_ac_params[3] = ac_vo; - -#ifdef CONFIG_IEEE80211N - conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED; -#endif /* CONFIG_IEEE80211N */ - - return conf; -} - - -int hostapd_mac_comp(const void *a, const void *b) -{ - return os_memcmp(a, b, sizeof(macaddr)); -} - - -int hostapd_mac_comp_empty(const void *a) -{ - macaddr empty = { 0 }; - return os_memcmp(a, empty, sizeof(macaddr)); -} +#endif /* CONFIG_NO_VLAN */ static int hostapd_acl_comp(const void *a, const void *b) @@ -357,133 +194,6 @@ static int hostapd_config_read_maclist(const char *fname, } -static int hostapd_config_read_wpa_psk(const char *fname, - struct hostapd_ssid *ssid) -{ - FILE *f; - char buf[128], *pos; - int line = 0, ret = 0, len, ok; - u8 addr[ETH_ALEN]; - struct hostapd_wpa_psk *psk; - - if (!fname) - return 0; - - f = fopen(fname, "r"); - if (!f) { - wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname); - return -1; - } - - while (fgets(buf, sizeof(buf), f)) { - line++; - - if (buf[0] == '#') - continue; - pos = buf; - while (*pos != '\0') { - if (*pos == '\n') { - *pos = '\0'; - break; - } - pos++; - } - if (buf[0] == '\0') - continue; - - if (hwaddr_aton(buf, addr)) { - wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on " - "line %d in '%s'", buf, line, fname); - ret = -1; - break; - } - - psk = os_zalloc(sizeof(*psk)); - if (psk == NULL) { - wpa_printf(MSG_ERROR, "WPA PSK allocation failed"); - ret = -1; - break; - } - if (is_zero_ether_addr(addr)) - psk->group = 1; - else - os_memcpy(psk->addr, addr, ETH_ALEN); - - pos = buf + 17; - if (*pos == '\0') { - wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'", - line, fname); - os_free(psk); - ret = -1; - break; - } - pos++; - - ok = 0; - len = os_strlen(pos); - if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0) - ok = 1; - else if (len >= 8 && len < 64) { - pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len, - 4096, psk->psk, PMK_LEN); - ok = 1; - } - if (!ok) { - wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in " - "'%s'", pos, line, fname); - os_free(psk); - ret = -1; - break; - } - - psk->next = ssid->wpa_psk; - ssid->wpa_psk = psk; - } - - fclose(f); - - return ret; -} - - -int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf) -{ - struct hostapd_ssid *ssid = &conf->ssid; - - if (ssid->wpa_passphrase != NULL) { - if (ssid->wpa_psk != NULL) { - wpa_printf(MSG_ERROR, "Warning: both WPA PSK and " - "passphrase set. Using passphrase."); - os_free(ssid->wpa_psk); - } - ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); - if (ssid->wpa_psk == NULL) { - wpa_printf(MSG_ERROR, "Unable to alloc space for PSK"); - return -1; - } - wpa_hexdump_ascii(MSG_DEBUG, "SSID", - (u8 *) ssid->ssid, ssid->ssid_len); - wpa_hexdump_ascii(MSG_DEBUG, "PSK (ASCII passphrase)", - (u8 *) ssid->wpa_passphrase, - os_strlen(ssid->wpa_passphrase)); - pbkdf2_sha1(ssid->wpa_passphrase, - ssid->ssid, ssid->ssid_len, - 4096, ssid->wpa_psk->psk, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "PSK (from passphrase)", - ssid->wpa_psk->psk, PMK_LEN); - ssid->wpa_psk->group = 1; - } - - if (ssid->wpa_psk_file) { - if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file, - &conf->ssid)) - return -1; - } - - return 0; -} - - #ifdef EAP_SERVER static int hostapd_config_read_eap_user(const char *fname, struct hostapd_bss_config *conf) @@ -761,6 +471,7 @@ static int hostapd_config_read_eap_user(const char *fname, #endif /* EAP_SERVER */ +#ifndef CONFIG_NO_RADIUS static int hostapd_config_read_radius_addr(struct hostapd_radius_server **server, int *num_server, const char *val, int def_port, @@ -786,6 +497,7 @@ hostapd_config_read_radius_addr(struct hostapd_radius_server **server, return ret; } +#endif /* CONFIG_NO_RADIUS */ static int hostapd_config_parse_key_mgmt(int line, const char *value) @@ -899,86 +611,6 @@ static int hostapd_config_parse_cipher(int line, const char *value) } -static int hostapd_config_check_bss(struct hostapd_bss_config *bss, - struct hostapd_config *conf) -{ - if (bss->ieee802_1x && !bss->eap_server && - !bss->radius->auth_servers) { - wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no " - "EAP authenticator configured)."); - return -1; - } - - if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) && - bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL && - bss->ssid.wpa_psk_file == NULL) { - wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase " - "is not configured."); - return -1; - } - - if (hostapd_mac_comp_empty(bss->bssid) != 0) { - size_t i; - - for (i = 0; i < conf->num_bss; i++) { - if ((&conf->bss[i] != bss) && - (hostapd_mac_comp(conf->bss[i].bssid, - bss->bssid) == 0)) { - wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR - " on interface '%s' and '%s'.", - MAC2STR(bss->bssid), - conf->bss[i].iface, bss->iface); - return -1; - } - } - } - -#ifdef CONFIG_IEEE80211R - if ((bss->wpa_key_mgmt & - (WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_FT_IEEE8021X)) && - (bss->nas_identifier == NULL || - os_strlen(bss->nas_identifier) < 1 || - os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) { - wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires " - "nas_identifier to be configured as a 1..48 octet " - "string"); - return -1; - } -#endif /* CONFIG_IEEE80211R */ - -#ifdef CONFIG_IEEE80211N - if (conf->ieee80211n && bss->wpa && - !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && - !(bss->rsn_pairwise & WPA_CIPHER_CCMP)) { - wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " - "requires CCMP to be enabled"); - return -1; - } -#endif /* CONFIG_IEEE80211N */ - - return 0; -} - - -static int hostapd_config_check(struct hostapd_config *conf) -{ - size_t i; - - if (conf->ieee80211d && (!conf->country[0] || !conf->country[1])) { - wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without " - "setting the country_code"); - return -1; - } - - for (i = 0; i < conf->num_bss; i++) { - if (hostapd_config_check_bss(&conf->bss[i], conf)) - return -1; - } - - return 0; -} - - static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx, char *val) { @@ -1089,6 +721,26 @@ static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname) } +/* convert floats with one decimal place to value*10 int, i.e., + * "1.5" will return 15 */ +static int hostapd_config_read_int10(const char *value) +{ + int i, d; + char *pos; + + i = atoi(value); + pos = os_strchr(value, '.'); + d = 0; + if (pos) { + pos++; + if (*pos >= '0' && *pos <= '9') + d = *pos - '0'; + } + + return i * 10 + d; +} + + static int valid_cw(int cw) { return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 || @@ -1389,6 +1041,86 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf, #endif /* CONFIG_IEEE80211N */ +static int hostapd_config_check_bss(struct hostapd_bss_config *bss, + struct hostapd_config *conf) +{ + if (bss->ieee802_1x && !bss->eap_server && + !bss->radius->auth_servers) { + wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no " + "EAP authenticator configured)."); + return -1; + } + + if (bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) && + bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL && + bss->ssid.wpa_psk_file == NULL) { + wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase " + "is not configured."); + return -1; + } + + if (hostapd_mac_comp_empty(bss->bssid) != 0) { + size_t i; + + for (i = 0; i < conf->num_bss; i++) { + if ((&conf->bss[i] != bss) && + (hostapd_mac_comp(conf->bss[i].bssid, + bss->bssid) == 0)) { + wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR + " on interface '%s' and '%s'.", + MAC2STR(bss->bssid), + conf->bss[i].iface, bss->iface); + return -1; + } + } + } + +#ifdef CONFIG_IEEE80211R + if ((bss->wpa_key_mgmt & + (WPA_KEY_MGMT_FT_PSK | WPA_KEY_MGMT_FT_IEEE8021X)) && + (bss->nas_identifier == NULL || + os_strlen(bss->nas_identifier) < 1 || + os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) { + wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires " + "nas_identifier to be configured as a 1..48 octet " + "string"); + return -1; + } +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_IEEE80211N + if (conf->ieee80211n && bss->wpa && + !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && + !(bss->rsn_pairwise & WPA_CIPHER_CCMP)) { + wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " + "requires CCMP to be enabled"); + return -1; + } +#endif /* CONFIG_IEEE80211N */ + + return 0; +} + + +static int hostapd_config_check(struct hostapd_config *conf) +{ + size_t i; + + if (conf->ieee80211d && (!conf->country[0] || !conf->country[1])) { + wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without " + "setting the country_code"); + return -1; + } + + for (i = 0; i < conf->num_bss; i++) { + if (hostapd_config_check_bss(&conf->bss[i], conf)) + return -1; + } + + return 0; +} + + /** * hostapd_config_read - Read and parse a configuration file * @fname: Configuration file name (including path, if needed) @@ -1417,6 +1149,16 @@ struct hostapd_config * hostapd_config_read(const char *fname) fclose(f); return NULL; } + + /* set default driver based on configuration */ + conf->driver = wpa_drivers[0]; + if (conf->driver == NULL) { + wpa_printf(MSG_ERROR, "No driver wrappers registered!"); + hostapd_config_free(conf); + fclose(f); + return NULL; + } + bss = conf->last_bss = conf->bss; while (fgets(buf, sizeof(buf), f)) { @@ -1455,10 +1197,10 @@ struct hostapd_config * hostapd_config_read(const char *fname) int j; /* clear to get error below if setting is invalid */ conf->driver = NULL; - for (j = 0; hostapd_drivers[j]; j++) { - if (os_strcmp(pos, hostapd_drivers[j]->name) == - 0) { - conf->driver = hostapd_drivers[j]; + for (j = 0; wpa_drivers[j]; j++) { + if (os_strcmp(pos, wpa_drivers[j]->name) == 0) + { + conf->driver = wpa_drivers[j]; break; } } @@ -1520,6 +1262,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) line, pos); errors++; } + } else if (os_strcmp(buf, "wds_sta") == 0) { + bss->wds_sta = atoi(pos); } else if (os_strcmp(buf, "ap_max_inactivity") == 0) { bss->ap_max_inactivity = atoi(pos); } else if (os_strcmp(buf, "country_code") == 0) { @@ -1569,7 +1313,7 @@ struct hostapd_config * hostapd_config_read(const char *fname) } else if (os_strcmp(buf, "dh_file") == 0) { os_free(bss->dh_file); bss->dh_file = os_strdup(pos); -#ifdef EAP_FAST +#ifdef EAP_SERVER_FAST } else if (os_strcmp(buf, "pac_opaque_encr_key") == 0) { os_free(bss->pac_opaque_encr_key); bss->pac_opaque_encr_key = os_malloc(16); @@ -1611,18 +1355,18 @@ struct hostapd_config * hostapd_config_read(const char *fname) bss->pac_key_lifetime = atoi(pos); } else if (os_strcmp(buf, "pac_key_refresh_time") == 0) { bss->pac_key_refresh_time = atoi(pos); -#endif /* EAP_FAST */ -#ifdef EAP_SIM +#endif /* EAP_SERVER_FAST */ +#ifdef EAP_SERVER_SIM } else if (os_strcmp(buf, "eap_sim_db") == 0) { os_free(bss->eap_sim_db); bss->eap_sim_db = os_strdup(pos); } else if (os_strcmp(buf, "eap_sim_aka_result_ind") == 0) { bss->eap_sim_aka_result_ind = atoi(pos); -#endif /* EAP_SIM */ -#ifdef EAP_TNC +#endif /* EAP_SERVER_SIM */ +#ifdef EAP_SERVER_TNC } else if (os_strcmp(buf, "tnc") == 0) { bss->tnc = atoi(pos); -#endif /* EAP_TNC */ +#endif /* EAP_SERVER_TNC */ #endif /* EAP_SERVER */ } else if (os_strcmp(buf, "eap_message") == 0) { char *term; @@ -1697,6 +1441,7 @@ struct hostapd_config * hostapd_config_read(const char *fname) } } else if (os_strcmp(buf, "nas_identifier") == 0) { bss->nas_identifier = os_strdup(pos); +#ifndef CONFIG_NO_RADIUS } else if (os_strcmp(buf, "auth_server_addr") == 0) { if (hostapd_config_read_radius_addr( &bss->radius->auth_servers, @@ -1750,7 +1495,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) bss->radius->retry_primary_interval = atoi(pos); } else if (os_strcmp(buf, "radius_acct_interim_interval") == 0) { - bss->radius->acct_interim_interval = atoi(pos); + bss->acct_interim_interval = atoi(pos); +#endif /* CONFIG_NO_RADIUS */ } else if (os_strcmp(buf, "auth_algs") == 0) { bss->auth_algs = atoi(pos); if (bss->auth_algs == 0) { @@ -1896,6 +1642,7 @@ struct hostapd_config * hostapd_config_read(const char *fname) } else if (os_strcmp(buf, "pmk_r1_push") == 0) { bss->pmk_r1_push = atoi(pos); #endif /* CONFIG_IEEE80211R */ +#ifndef CONFIG_NO_CTRL_IFACE } else if (os_strcmp(buf, "ctrl_interface") == 0) { os_free(bss->ctrl_interface); bss->ctrl_interface = os_strdup(pos); @@ -1927,6 +1674,7 @@ struct hostapd_config * hostapd_config_read(const char *fname) wpa_printf(MSG_DEBUG, "ctrl_interface_group=%d", bss->ctrl_interface_gid); #endif /* CONFIG_NATIVE_WINDOWS */ +#endif /* CONFIG_NO_CTRL_IFACE */ #ifdef RADIUS_SERVER } else if (os_strcmp(buf, "radius_server_clients") == 0) { os_free(bss->radius_server_clients); @@ -2022,8 +1770,6 @@ struct hostapd_config * hostapd_config_read(const char *fname) conf->preamble = LONG_PREAMBLE; } else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) { bss->ignore_broadcast_ssid = atoi(pos); - } else if (os_strcmp(buf, "bridge_packets") == 0) { - conf->bridge_packets = atoi(pos); } else if (os_strcmp(buf, "wep_default_key") == 0) { bss->ssid.wep.idx = atoi(pos); if (bss->ssid.wep.idx > 3) { @@ -2042,6 +1788,7 @@ struct hostapd_config * hostapd_config_read(const char *fname) "key '%s'", line, buf); errors++; } +#ifndef CONFIG_NO_VLAN } else if (os_strcmp(buf, "dynamic_vlan") == 0) { bss->ssid.dynamic_vlan = atoi(pos); } else if (os_strcmp(buf, "vlan_file") == 0) { @@ -2054,12 +1801,7 @@ struct hostapd_config * hostapd_config_read(const char *fname) } else if (os_strcmp(buf, "vlan_tagged_interface") == 0) { bss->ssid.vlan_tagged_interface = os_strdup(pos); #endif /* CONFIG_FULL_DYNAMIC_VLAN */ - } else if (os_strcmp(buf, "passive_scan_interval") == 0) { - conf->passive_scan_interval = atoi(pos); - } else if (os_strcmp(buf, "passive_scan_listen") == 0) { - conf->passive_scan_listen = atoi(pos); - } else if (os_strcmp(buf, "passive_scan_mode") == 0) { - conf->passive_scan_mode = atoi(pos); +#endif /* CONFIG_NO_VLAN */ } else if (os_strcmp(buf, "ap_table_max_size") == 0) { conf->ap_table_max_size = atoi(pos); } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) { @@ -2073,6 +1815,8 @@ struct hostapd_config * hostapd_config_read(const char *fname) } else if (os_strcmp(buf, "wme_enabled") == 0 || os_strcmp(buf, "wmm_enabled") == 0) { bss->wmm_enabled = atoi(pos); + } else if (os_strcmp(buf, "uapsd_advertisement_enabled") == 0) { + bss->wmm_uapsd = atoi(pos); } else if (os_strncmp(buf, "wme_ac_", 7) == 0 || os_strncmp(buf, "wmm_ac_", 7) == 0) { if (hostapd_config_wmm_ac(conf, buf, pos)) { @@ -2087,13 +1831,7 @@ struct hostapd_config * hostapd_config_read(const char *fname) errors++; } } else if (os_strcmp(buf, "bssid") == 0) { - if (bss == conf->bss && - (!conf->driver || !conf->driver->init_bssid)) { - wpa_printf(MSG_ERROR, "Line %d: bssid item " - "not allowed for the default " - "interface and this driver", line); - errors++; - } else if (hwaddr_aton(pos, bss->bssid)) { + if (hwaddr_aton(pos, bss->bssid)) { wpa_printf(MSG_ERROR, "Line %d: invalid bssid " "item", line); errors++; @@ -2309,314 +2047,3 @@ struct hostapd_config * hostapd_config_read(const char *fname) return conf; } - - -int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b) -{ - int i; - - if (a->idx != b->idx || a->default_len != b->default_len) - return 1; - for (i = 0; i < NUM_WEP_KEYS; i++) - if (a->len[i] != b->len[i] || - os_memcmp(a->key[i], b->key[i], a->len[i]) != 0) - return 1; - return 0; -} - - -static void hostapd_config_free_radius(struct hostapd_radius_server *servers, - int num_servers) -{ - int i; - - for (i = 0; i < num_servers; i++) { - os_free(servers[i].shared_secret); - } - os_free(servers); -} - - -static void hostapd_config_free_eap_user(struct hostapd_eap_user *user) -{ - os_free(user->identity); - os_free(user->password); - os_free(user); -} - - -static void hostapd_config_free_wep(struct hostapd_wep_keys *keys) -{ - int i; - for (i = 0; i < NUM_WEP_KEYS; i++) { - os_free(keys->key[i]); - keys->key[i] = NULL; - } -} - - -static void hostapd_config_free_bss(struct hostapd_bss_config *conf) -{ - struct hostapd_wpa_psk *psk, *prev; - struct hostapd_eap_user *user, *prev_user; - - if (conf == NULL) - return; - - psk = conf->ssid.wpa_psk; - while (psk) { - prev = psk; - psk = psk->next; - os_free(prev); - } - - os_free(conf->ssid.wpa_passphrase); - os_free(conf->ssid.wpa_psk_file); -#ifdef CONFIG_FULL_DYNAMIC_VLAN - os_free(conf->ssid.vlan_tagged_interface); -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - user = conf->eap_user; - while (user) { - prev_user = user; - user = user->next; - hostapd_config_free_eap_user(prev_user); - } - - os_free(conf->dump_log_name); - os_free(conf->eap_req_id_text); - os_free(conf->accept_mac); - os_free(conf->deny_mac); - os_free(conf->nas_identifier); - hostapd_config_free_radius(conf->radius->auth_servers, - conf->radius->num_auth_servers); - hostapd_config_free_radius(conf->radius->acct_servers, - conf->radius->num_acct_servers); - os_free(conf->rsn_preauth_interfaces); - os_free(conf->ctrl_interface); - os_free(conf->ca_cert); - os_free(conf->server_cert); - os_free(conf->private_key); - os_free(conf->private_key_passwd); - os_free(conf->dh_file); - os_free(conf->pac_opaque_encr_key); - os_free(conf->eap_fast_a_id); - os_free(conf->eap_fast_a_id_info); - os_free(conf->eap_sim_db); - os_free(conf->radius_server_clients); - os_free(conf->test_socket); - os_free(conf->radius); - hostapd_config_free_vlan(conf); - if (conf->ssid.dyn_vlan_keys) { - struct hostapd_ssid *ssid = &conf->ssid; - size_t i; - for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) { - if (ssid->dyn_vlan_keys[i] == NULL) - continue; - hostapd_config_free_wep(ssid->dyn_vlan_keys[i]); - os_free(ssid->dyn_vlan_keys[i]); - } - os_free(ssid->dyn_vlan_keys); - ssid->dyn_vlan_keys = NULL; - } - -#ifdef CONFIG_IEEE80211R - { - struct ft_remote_r0kh *r0kh, *r0kh_prev; - struct ft_remote_r1kh *r1kh, *r1kh_prev; - - r0kh = conf->r0kh_list; - conf->r0kh_list = NULL; - while (r0kh) { - r0kh_prev = r0kh; - r0kh = r0kh->next; - os_free(r0kh_prev); - } - - r1kh = conf->r1kh_list; - conf->r1kh_list = NULL; - while (r1kh) { - r1kh_prev = r1kh; - r1kh = r1kh->next; - os_free(r1kh_prev); - } - } -#endif /* CONFIG_IEEE80211R */ - -#ifdef CONFIG_WPS - os_free(conf->wps_pin_requests); - os_free(conf->device_name); - os_free(conf->manufacturer); - os_free(conf->model_name); - os_free(conf->model_number); - os_free(conf->serial_number); - os_free(conf->device_type); - os_free(conf->config_methods); - os_free(conf->ap_pin); - os_free(conf->extra_cred); - os_free(conf->ap_settings); - os_free(conf->upnp_iface); - os_free(conf->friendly_name); - os_free(conf->manufacturer_url); - os_free(conf->model_description); - os_free(conf->model_url); - os_free(conf->upc); -#endif /* CONFIG_WPS */ -} - - -/** - * hostapd_config_free - Free hostapd configuration - * @conf: Configuration data from hostapd_config_read(). - */ -void hostapd_config_free(struct hostapd_config *conf) -{ - size_t i; - - if (conf == NULL) - return; - - for (i = 0; i < conf->num_bss; i++) - hostapd_config_free_bss(&conf->bss[i]); - os_free(conf->bss); - os_free(conf->supported_rates); - os_free(conf->basic_rates); - - os_free(conf); -} - - -/** - * hostapd_maclist_found - Find a MAC address from a list - * @list: MAC address list - * @num_entries: Number of addresses in the list - * @addr: Address to search for - * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed - * Returns: 1 if address is in the list or 0 if not. - * - * Perform a binary search for given MAC address from a pre-sorted list. - */ -int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, - const u8 *addr, int *vlan_id) -{ - int start, end, middle, res; - - start = 0; - end = num_entries - 1; - - while (start <= end) { - middle = (start + end) / 2; - res = os_memcmp(list[middle].addr, addr, ETH_ALEN); - if (res == 0) { - if (vlan_id) - *vlan_id = list[middle].vlan_id; - return 1; - } - if (res < 0) - start = middle + 1; - else - end = middle - 1; - } - - return 0; -} - - -int hostapd_rate_found(int *list, int rate) -{ - int i; - - if (list == NULL) - return 0; - - for (i = 0; list[i] >= 0; i++) - if (list[i] == rate) - return 1; - - return 0; -} - - -const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id) -{ - struct hostapd_vlan *v = vlan; - while (v) { - if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD) - return v->ifname; - v = v->next; - } - return NULL; -} - - -const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, - const u8 *addr, const u8 *prev_psk) -{ - struct hostapd_wpa_psk *psk; - int next_ok = prev_psk == NULL; - - for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) { - if (next_ok && - (psk->group || os_memcmp(psk->addr, addr, ETH_ALEN) == 0)) - return psk->psk; - - if (psk->psk == prev_psk) - next_ok = 1; - } - - return NULL; -} - - -const struct hostapd_eap_user * -hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity, - size_t identity_len, int phase2) -{ - struct hostapd_eap_user *user = conf->eap_user; - -#ifdef CONFIG_WPS - if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN && - os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) { - static struct hostapd_eap_user wsc_enrollee; - os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee)); - wsc_enrollee.methods[0].method = eap_server_get_type( - "WSC", &wsc_enrollee.methods[0].vendor); - return &wsc_enrollee; - } - - if (conf->wps_state && conf->ap_pin && - identity_len == WSC_ID_REGISTRAR_LEN && - os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) { - static struct hostapd_eap_user wsc_registrar; - os_memset(&wsc_registrar, 0, sizeof(wsc_registrar)); - wsc_registrar.methods[0].method = eap_server_get_type( - "WSC", &wsc_registrar.methods[0].vendor); - wsc_registrar.password = (u8 *) conf->ap_pin; - wsc_registrar.password_len = os_strlen(conf->ap_pin); - return &wsc_registrar; - } -#endif /* CONFIG_WPS */ - - while (user) { - if (!phase2 && user->identity == NULL) { - /* Wildcard match */ - break; - } - - if (user->phase2 == !!phase2 && user->wildcard_prefix && - identity_len >= user->identity_len && - os_memcmp(user->identity, identity, user->identity_len) == - 0) { - /* Wildcard prefix match */ - break; - } - - if (user->phase2 == !!phase2 && - user->identity_len == identity_len && - os_memcmp(user->identity, identity, identity_len) == 0) - break; - user = user->next; - } - - return user; -} diff --git a/contrib/wpa/hostapd/config_file.h b/contrib/wpa/hostapd/config_file.h new file mode 100644 index 000000000000..7111a9a3167f --- /dev/null +++ b/contrib/wpa/hostapd/config_file.h @@ -0,0 +1,20 @@ +/* + * hostapd / Configuration file parser + * Copyright (c) 2003-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef CONFIG_FILE_H +#define CONFIG_FILE_H + +struct hostapd_config * hostapd_config_read(const char *fname); + +#endif /* CONFIG_FILE_H */ diff --git a/contrib/wpa/hostapd/ctrl_iface.c b/contrib/wpa/hostapd/ctrl_iface.c index 9dec7247cdd7..9c47ba8bb76d 100644 --- a/contrib/wpa/hostapd/ctrl_iface.c +++ b/contrib/wpa/hostapd/ctrl_iface.c @@ -1,6 +1,6 @@ /* * hostapd / UNIX domain socket -based control interface - * Copyright (c) 2004-2008, Jouni Malinen + * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,7 +12,7 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" #ifndef CONFIG_NATIVE_WINDOWS @@ -20,17 +20,21 @@ #include #include -#include "hostapd.h" -#include "eloop.h" -#include "config.h" -#include "ieee802_1x.h" -#include "wpa.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "drivers/driver.h" #include "radius/radius_client.h" -#include "ieee802_11.h" +#include "ap/hostapd.h" +#include "ap/ap_config.h" +#include "ap/ieee802_1x.h" +#include "ap/wpa_auth.h" +#include "ap/ieee802_11.h" +#include "ap/sta_info.h" +#include "ap/accounting.h" +#include "ap/wps_hostapd.h" +#include "ap/ctrl_iface_ap.h" #include "ctrl_iface.h" -#include "sta_info.h" -#include "accounting.h" -#include "wps_hostapd.h" struct wpa_ctrl_dst { @@ -125,84 +129,6 @@ static int hostapd_ctrl_iface_level(struct hostapd_data *hapd, } -static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, - struct sta_info *sta, - char *buf, size_t buflen) -{ - int len, res, ret; - - if (sta == NULL) { - ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; - } - - len = 0; - ret = os_snprintf(buf + len, buflen - len, MACSTR "\n", - MAC2STR(sta->addr)); - if (ret < 0 || (size_t) ret >= buflen - len) - return len; - len += ret; - - res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len); - if (res >= 0) - len += res; - res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len); - if (res >= 0) - len += res; - res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len); - if (res >= 0) - len += res; - - return len; -} - - -static int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd, - char *buf, size_t buflen) -{ - return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen); -} - - -static int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, - const char *txtaddr, - char *buf, size_t buflen) -{ - u8 addr[ETH_ALEN]; - int ret; - - if (hwaddr_aton(txtaddr, addr)) { - ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; - } - return hostapd_ctrl_iface_sta_mib(hapd, ap_get_sta(hapd, addr), - buf, buflen); -} - - -static int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, - const char *txtaddr, - char *buf, size_t buflen) -{ - u8 addr[ETH_ALEN]; - struct sta_info *sta; - int ret; - - if (hwaddr_aton(txtaddr, addr) || - (sta = ap_get_sta(hapd, addr)) == NULL) { - ret = os_snprintf(buf, buflen, "FAIL\n"); - if (ret < 0 || (size_t) ret >= buflen) - return 0; - return ret; - } - return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen); -} - - static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, const char *txtaddr) { @@ -229,7 +155,100 @@ static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, } +static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, + const char *txtaddr) +{ + u8 addr[ETH_ALEN]; + struct sta_info *sta; + const char *pos; + + wpa_printf(MSG_DEBUG, "CTRL_IFACE DEAUTHENTICATE %s", txtaddr); + + if (hwaddr_aton(txtaddr, addr)) + return -1; + + pos = os_strstr(txtaddr, " test="); + if (pos) { + struct ieee80211_mgmt mgmt; + int encrypt; + if (hapd->driver->send_frame == NULL) + return -1; + pos += 6; + encrypt = atoi(pos); + os_memset(&mgmt, 0, sizeof(mgmt)); + mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_DEAUTH); + os_memcpy(mgmt.da, addr, ETH_ALEN); + os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); + os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); + mgmt.u.deauth.reason_code = + host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); + if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt, + IEEE80211_HDRLEN + + sizeof(mgmt.u.deauth), + encrypt) < 0) + return -1; + return 0; + } + + hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); + sta = ap_get_sta(hapd, addr); + if (sta) + ap_sta_deauthenticate(hapd, sta, + WLAN_REASON_PREV_AUTH_NOT_VALID); + + return 0; +} + + +static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, + const char *txtaddr) +{ + u8 addr[ETH_ALEN]; + struct sta_info *sta; + const char *pos; + + wpa_printf(MSG_DEBUG, "CTRL_IFACE DISASSOCIATE %s", txtaddr); + + if (hwaddr_aton(txtaddr, addr)) + return -1; + + pos = os_strstr(txtaddr, " test="); + if (pos) { + struct ieee80211_mgmt mgmt; + int encrypt; + if (hapd->driver->send_frame == NULL) + return -1; + pos += 6; + encrypt = atoi(pos); + os_memset(&mgmt, 0, sizeof(mgmt)); + mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_DISASSOC); + os_memcpy(mgmt.da, addr, ETH_ALEN); + os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); + os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); + mgmt.u.disassoc.reason_code = + host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); + if (hapd->driver->send_frame(hapd->drv_priv, (u8 *) &mgmt, + IEEE80211_HDRLEN + + sizeof(mgmt.u.deauth), + encrypt) < 0) + return -1; + return 0; + } + + hapd->drv.sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); + sta = ap_get_sta(hapd, addr); + if (sta) + ap_sta_disassociate(hapd, sta, + WLAN_REASON_PREV_AUTH_NOT_VALID); + + return 0; +} + + #ifdef CONFIG_IEEE80211W +#ifdef NEED_AP_MLME static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, const char *txtaddr) { @@ -238,14 +257,15 @@ static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd, wpa_printf(MSG_DEBUG, "CTRL_IFACE SA_QUERY %s", txtaddr); - if (hwaddr_aton(txtaddr, addr)) + if (hwaddr_aton(txtaddr, addr) || + os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) return -1; - os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN); ieee802_11_send_sa_query_req(hapd, addr, trans_id); return 0; } +#endif /* NEED_AP_MLME */ #endif /* CONFIG_IEEE80211W */ @@ -269,6 +289,83 @@ static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt) return hostapd_wps_add_pin(hapd, txt, pin, timeout); } + + +#ifdef CONFIG_WPS_OOB +static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt) +{ + char *path, *method, *name; + + path = os_strchr(txt, ' '); + if (path == NULL) + return -1; + *path++ = '\0'; + + method = os_strchr(path, ' '); + if (method == NULL) + return -1; + *method++ = '\0'; + + name = os_strchr(method, ' '); + if (name != NULL) + *name++ = '\0'; + + return hostapd_wps_start_oob(hapd, txt, path, method, name); +} +#endif /* CONFIG_WPS_OOB */ + + +static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt, + char *buf, size_t buflen) +{ + int timeout = 300; + char *pos; + const char *pin_txt; + + pos = os_strchr(txt, ' '); + if (pos) + *pos++ = '\0'; + + if (os_strcmp(txt, "disable") == 0) { + hostapd_wps_ap_pin_disable(hapd); + return os_snprintf(buf, buflen, "OK\n"); + } + + if (os_strcmp(txt, "random") == 0) { + if (pos) + timeout = atoi(pos); + pin_txt = hostapd_wps_ap_pin_random(hapd, timeout); + if (pin_txt == NULL) + return -1; + return os_snprintf(buf, buflen, "%s", pin_txt); + } + + if (os_strcmp(txt, "get") == 0) { + pin_txt = hostapd_wps_ap_pin_get(hapd); + if (pin_txt == NULL) + return -1; + return os_snprintf(buf, buflen, "%s", pin_txt); + } + + if (os_strcmp(txt, "set") == 0) { + char *pin; + if (pos == NULL) + return -1; + pin = pos; + pos = os_strchr(pos, ' '); + if (pos) { + *pos++ = '\0'; + timeout = atoi(pos); + } + if (os_strlen(pin) > buflen) + return -1; + if (hostapd_wps_ap_pin_set(hapd, pin, timeout) < 0) + return -1; + return os_snprintf(buf, buflen, "%s", pin); + } + + return -1; +} #endif /* CONFIG_WPS */ @@ -324,6 +421,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, else reply_len += res; } +#ifndef CONFIG_NO_RADIUS if (reply_len >= 0) { res = radius_client_get_mib(hapd->radius, reply + reply_len, @@ -333,6 +431,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, else reply_len += res; } +#endif /* CONFIG_NO_RADIUS */ } else if (os_strcmp(buf, "STA-FIRST") == 0) { reply_len = hostapd_ctrl_iface_sta_first(hapd, reply, reply_size); @@ -355,10 +454,18 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, } else if (os_strncmp(buf, "NEW_STA ", 8) == 0) { if (hostapd_ctrl_iface_new_sta(hapd, buf + 8)) reply_len = -1; + } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) { + if (hostapd_ctrl_iface_deauthenticate(hapd, buf + 15)) + reply_len = -1; + } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) { + if (hostapd_ctrl_iface_disassociate(hapd, buf + 13)) + reply_len = -1; #ifdef CONFIG_IEEE80211W +#ifdef NEED_AP_MLME } else if (os_strncmp(buf, "SA_QUERY ", 9) == 0) { if (hostapd_ctrl_iface_sa_query(hapd, buf + 9)) reply_len = -1; +#endif /* NEED_AP_MLME */ #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WPS } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { @@ -367,6 +474,14 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, } else if (os_strcmp(buf, "WPS_PBC") == 0) { if (hostapd_wps_button_pushed(hapd)) reply_len = -1; +#ifdef CONFIG_WPS_OOB + } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) { + if (hostapd_ctrl_iface_wps_oob(hapd, buf + 8)) + reply_len = -1; +#endif /* CONFIG_WPS_OOB */ + } else if (os_strncmp(buf, "WPS_AP_PIN ", 11) == 0) { + reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11, + reply, reply_size); #endif /* CONFIG_WPS */ } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); @@ -507,6 +622,7 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd) hapd->ctrl_sock = s; eloop_register_read_sock(s, hostapd_ctrl_iface_receive, hapd, NULL); + hapd->msg_ctx = hapd; wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb); return 0; diff --git a/contrib/wpa/hostapd/ctrl_iface.h b/contrib/wpa/hostapd/ctrl_iface.h index d86de8c94066..c997141a1510 100644 --- a/contrib/wpa/hostapd/ctrl_iface.h +++ b/contrib/wpa/hostapd/ctrl_iface.h @@ -15,7 +15,18 @@ #ifndef CTRL_IFACE_H #define CTRL_IFACE_H +#ifndef CONFIG_NO_CTRL_IFACE int hostapd_ctrl_iface_init(struct hostapd_data *hapd); void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd); +#else /* CONFIG_NO_CTRL_IFACE */ +static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd) +{ + return 0; +} + +static inline void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd) +{ +} +#endif /* CONFIG_NO_CTRL_IFACE */ #endif /* CTRL_IFACE_H */ diff --git a/contrib/wpa/hostapd/defconfig b/contrib/wpa/hostapd/defconfig index 96a023d2e65d..1d28c022fa46 100644 --- a/contrib/wpa/hostapd/defconfig +++ b/contrib/wpa/hostapd/defconfig @@ -19,9 +19,6 @@ CONFIG_DRIVER_HOSTAP=y #CONFIG_DRIVER_MADWIFI=y #CFLAGS += -I../../madwifi # change to the madwifi source directory -# Driver interface for Prism54 driver -#CONFIG_DRIVER_PRISM54=y - # Driver interface for drivers using the nl80211 kernel interface #CONFIG_DRIVER_NL80211=y # driver_nl80211.c requires a rather new libnl (version 1.1) which may not be @@ -35,6 +32,8 @@ CONFIG_DRIVER_HOSTAP=y #CONFIG_DRIVER_BSD=y #CFLAGS += -I/usr/local/include #LIBS += -L/usr/local/lib +#LIBS_p += -L/usr/local/lib +#LIBS_c += -L/usr/local/lib # Driver interface for no driver (e.g., RADIUS server only) #CONFIG_DRIVER_NONE=y @@ -142,3 +141,35 @@ CONFIG_IPV6=y # This can be used to reduce the size of the hostapd considerably if debugging # code is not needed. #CONFIG_NO_STDOUT_DEBUG=y + +# Remove support for RADIUS accounting +#CONFIG_NO_ACCOUNTING=y + +# Remove support for RADIUS +#CONFIG_NO_RADIUS=y + +# Remove support for VLANs +#CONFIG_NO_VLAN=y + +# Remove support for dumping state into a file on SIGUSR1 signal +# This can be used to reduce binary size at the cost of disabling a debugging +# option. +#CONFIG_NO_DUMP_STATE=y + +# Enable tracing code for developer debugging +# This tracks use of memory allocations and other registrations and reports +# incorrect use with a backtrace of call (or allocation) location. +#CONFIG_WPA_TRACE=y +# For BSD, comment out these. +#LIBS += -lexecinfo +#LIBS_p += -lexecinfo +#LIBS_c += -lexecinfo + +# Use libbfd to get more details for developer debugging +# This enables use of libbfd to get more detailed symbols for the backtraces +# generated by CONFIG_WPA_TRACE=y. +#CONFIG_WPA_TRACE_BFD=y +# For BSD, comment out these. +#LIBS += -lbfd -liberty -lz +#LIBS_p += -lbfd -liberty -lz +#LIBS_c += -lbfd -liberty -lz diff --git a/contrib/wpa/hostapd/doc/code_structure.doxygen b/contrib/wpa/hostapd/doc/code_structure.doxygen deleted file mode 100644 index fdcf725b5d7f..000000000000 --- a/contrib/wpa/hostapd/doc/code_structure.doxygen +++ /dev/null @@ -1,5 +0,0 @@ -/** -\page code_structure Structure of the source code - - -*/ diff --git a/contrib/wpa/hostapd/doc/ctrl_iface.doxygen b/contrib/wpa/hostapd/doc/ctrl_iface.doxygen deleted file mode 100644 index 76cfc6a6b79c..000000000000 --- a/contrib/wpa/hostapd/doc/ctrl_iface.doxygen +++ /dev/null @@ -1,66 +0,0 @@ -/** -\page ctrl_iface_page Control interface - -hostapd implements a control interface that can be used by -external programs to control the operations of the hostapd -daemon and to get status information and event notifications. There is -a small C library, in a form of a single C file, wpa_ctrl.c, that -provides helper functions to facilitate the use of the control -interface. External programs can link this file into them and then use -the library functions documented in wpa_ctrl.h to interact with -%wpa_supplicant. This library can also be used with C++. hostapd_cli.c -is an example program using this library. - -There are multiple mechanisms for inter-process communication. For -example, Linux version of hostapd is using UNIX domain sockets for the -control interface. The use of the functions defined in wpa_ctrl.h can -be used to hide the details of the used IPC from external programs. - - -\section using_ctrl_iface Using the control interface - -External programs, e.g., a GUI or a configuration utility, that need to -communicate with hostapd should link in wpa_ctrl.c. This -allows them to use helper functions to open connection to the control -interface with wpa_ctrl_open() and to send commands with -wpa_ctrl_request(). - -hostapd uses the control interface for two types of communication: -commands and unsolicited event messages. Commands are a pair of -messages, a request from the external program and a response from -hostapd. These can be executed using wpa_ctrl_request(). -Unsolicited event messages are sent by hostapd to the control -interface connection without specific request from the external program -for receiving each message. However, the external program needs to -attach to the control interface with wpa_ctrl_attach() to receive these -unsolicited messages. - -If the control interface connection is used both for commands and -unsolicited event messages, there is potential for receiving an -unsolicited message between the command request and response. -wpa_ctrl_request() caller will need to supply a callback, msg_cb, -for processing these messages. Often it is easier to open two -control interface connections by calling wpa_ctrl_open() twice and -then use one of the connections for commands and the other one for -unsolicited messages. This way command request/response pairs will -not be broken by unsolicited messages. wpa_cli is an example of how -to use only one connection for both purposes and wpa_gui demonstrates -how to use two separate connections. - -Once the control interface connection is not needed anymore, it should -be closed by calling wpa_ctrl_close(). If the connection was used for -unsolicited event messages, it should be first detached by calling -wpa_ctrl_detach(). - - -\section ctrl_iface_cmds Control interface commands - -Following commands can be used with wpa_ctrl_request(): - -\subsection ctrl_iface_PING PING - -This command can be used to test whether hostapd is replying -to the control interface commands. The expected reply is \c PONG if the -connection is open and hostapd is processing commands. - -*/ diff --git a/contrib/wpa/hostapd/doc/doxygen.fast b/contrib/wpa/hostapd/doc/doxygen.fast deleted file mode 100644 index 650c73d817f4..000000000000 --- a/contrib/wpa/hostapd/doc/doxygen.fast +++ /dev/null @@ -1,238 +0,0 @@ -# Doxyfile 1.4.4 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = hostapd -PROJECT_NUMBER = 0.6.x -OUTPUT_DIRECTORY = hostapd/doc -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE = English -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -DISTRIBUTE_GROUP_DOC = NO -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = YES -OPTIMIZE_OUTPUT_JAVA = NO -SUBGROUPING = YES -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = NO -EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = YES -FILE_VERSION_FILTER = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = NO -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = YES -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = hostapd \ - src/common \ - src/crypto \ - src/eap_common \ - src/eap_server \ - src/l2_packet \ - src/radius \ - src/rsn_supp \ - src/tls \ - src/utils \ - src/wps -FILE_PATTERNS = *.c *.h *.doxygen -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = hostapd/doc -INPUT_FILTER = kerneldoc2doxygen.pl -FILTER_PATTERNS = -FILTER_SOURCE_FILES = YES -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION = NO -VERBATIM_HEADERS = NO -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 3 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NO -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = YES -USE_PDFLATEX = YES -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = RADIUS_SERVER EAP_SERVER EAP_SIM -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = NO -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = NO -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = NO -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = YES -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = NO -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -MAX_DOT_GRAPH_DEPTH = 1000 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO diff --git a/contrib/wpa/hostapd/doc/doxygen.full b/contrib/wpa/hostapd/doc/doxygen.full deleted file mode 100644 index f8c49bff7074..000000000000 --- a/contrib/wpa/hostapd/doc/doxygen.full +++ /dev/null @@ -1,238 +0,0 @@ -# Doxyfile 1.4.4 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = hostapd -PROJECT_NUMBER = 0.6.x -OUTPUT_DIRECTORY = hostapd/doc -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE = English -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -DISTRIBUTE_GROUP_DOC = NO -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = YES -OPTIMIZE_OUTPUT_JAVA = NO -SUBGROUPING = YES -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = NO -EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = YES -FILE_VERSION_FILTER = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = NO -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = YES -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = hostapd \ - src/common \ - src/crypto \ - src/eap_common \ - src/eap_server \ - src/l2_packet \ - src/radius \ - src/rsn_supp \ - src/tls \ - src/utils \ - src/wps -FILE_PATTERNS = *.c *.h *.doxygen -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = hostapd/doc -INPUT_FILTER = kerneldoc2doxygen.pl -FILTER_PATTERNS = -FILTER_SOURCE_FILES = YES -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION = NO -VERBATIM_HEADERS = NO -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 3 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NO -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = YES -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = YES -USE_PDFLATEX = YES -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = RADIUS_SERVER EAP_SERVER EAP_SIM -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = NO -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = NO -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = YES -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = NO -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -MAX_DOT_GRAPH_DEPTH = 1000 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = YES diff --git a/contrib/wpa/hostapd/doc/driver_wrapper.doxygen b/contrib/wpa/hostapd/doc/driver_wrapper.doxygen deleted file mode 100644 index 0ad196f2d6b6..000000000000 --- a/contrib/wpa/hostapd/doc/driver_wrapper.doxygen +++ /dev/null @@ -1,20 +0,0 @@ -/** -\page driver_wrapper Driver wrapper implementation (driver.h, drivers.c) - -All hardware and driver dependent functionality is in separate C files -that implement defined wrapper functions. Other parts -of the hostapd are designed to be hardware, driver, and operating -system independent. - -Driver wrappers need to implement whatever calls are used in the -target operating system/driver for controlling wireless LAN -devices. As an example, in case of Linux, these are mostly some glue -code and ioctl() calls and netlink message parsing for Linux Wireless -Extensions (WE). Since features required for WPA were added only recently to -Linux Wireless Extensions (in version 18), some driver specific code is used -in number of driver interface implementations. These driver dependent parts -can be replaced with generic code in driver_wext.c once the target driver -includes full support for WE-18. After that, all Linux drivers, at -least in theory, could use the same driver wrapper code. - -*/ diff --git a/contrib/wpa/hostapd/doc/eap.doxygen b/contrib/wpa/hostapd/doc/eap.doxygen deleted file mode 100644 index f0f135aa9598..000000000000 --- a/contrib/wpa/hostapd/doc/eap.doxygen +++ /dev/null @@ -1,56 +0,0 @@ -/** -\page eap_module EAP server implementation - -Extensible Authentication Protocol (EAP) is an authentication framework -defined in RFC 3748. hostapd uses a separate code module for EAP server -implementation. This module was designed to use only a minimal set of -direct function calls (mainly, to debug/event functions) in order for -it to be usable in other programs. The design of the EAP -implementation is based loosely on RFC 4137. The state machine is -defined in this RFC and so is the interface between the server state -machine and methods. As such, this RFC provides useful information for -understanding the EAP server implementation in hostapd. - -Some of the terminology used in EAP state machine is referring to -EAPOL (IEEE 802.1X), but there is no strict requirement on the lower -layer being IEEE 802.1X if EAP module is built for other programs than -%wpa_supplicant. These terms should be understood to refer to the -lower layer as defined in RFC 4137. - - -\section adding_eap_methods Adding EAP methods - -Each EAP method is implemented as a separate module, usually as one C -file named eap_ .c, e.g., eap_md5.c. All EAP -methods use the same interface between the server state machine and -method specific functions. This allows new EAP methods to be added -without modifying the core EAP state machine implementation. - -New EAP methods need to be registered by adding them into the build -(Makefile) and the EAP method registration list in the -eap_server_register_methods() function of eap_methods.c. Each EAP -method should use a build-time configuration option, e.g., EAP_TLS, in -order to make it possible to select which of the methods are included -in the build. - -EAP methods must implement the interface defined in eap_i.h. struct -eap_method defines the needed function pointers that each EAP method -must provide. In addition, the EAP type and name are registered using -this structure. This interface is based on section 4.4 of RFC 4137. - -It is recommended that the EAP methods would use generic helper -functions, eap_msg_alloc() and eap_hdr_validate() when processing -messages. This allows code sharing and can avoid missing some of the -needed validation steps for received packets. In addition, these -functions make it easier to change between expanded and legacy EAP -header, if needed. - -When adding an EAP method that uses a vendor specific EAP type -(Expanded Type as defined in RFC 3748, Chapter 5.7), the new method -must be registered by passing vendor id instead of EAP_VENDOR_IETF to -eap_server_method_alloc(). These methods must not try to emulate -expanded types by registering a legacy EAP method for type 254. See -eap_vendor_test.c for an example of an EAP method implementation that -is implemented as an expanded type. - -*/ diff --git a/contrib/wpa/hostapd/doc/hostapd.fig b/contrib/wpa/hostapd/doc/hostapd.fig deleted file mode 100644 index af3f0be19a9b..000000000000 --- a/contrib/wpa/hostapd/doc/hostapd.fig +++ /dev/null @@ -1,264 +0,0 @@ -#FIG 3.2 -Landscape -Center -Inches -Letter -100.00 -Single --2 -1200 2 -6 1875 4050 2925 4350 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1875 4050 2925 4050 2925 4350 1875 4350 1875 4050 -4 0 0 50 -1 0 12 0.0000 4 180 735 2025 4275 l2_packet\001 --6 -6 4725 1200 5925 1500 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4725 1200 5925 1200 5925 1500 4725 1500 4725 1200 -4 0 0 50 -1 0 12 0.0000 4 135 1005 4800 1425 GUI frontend\001 --6 -6 6000 2700 7200 3225 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 2700 7200 2700 7200 3225 6000 3225 6000 2700 -4 0 0 50 -1 0 12 0.0000 4 135 975 6075 2925 WPA/WPA2\001 -4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 3150 state machine\001 --6 -6 6000 4950 7200 5475 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 4950 7200 4950 7200 5475 6000 5475 6000 4950 -4 0 0 50 -1 0 12 0.0000 4 135 360 6075 5175 EAP\001 -4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 5400 state machine\001 --6 -6 4350 3900 5025 4425 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4350 3900 5025 3900 5025 4425 4350 4425 4350 3900 -4 0 0 50 -1 0 12 0.0000 4 105 420 4500 4125 event\001 -4 0 0 50 -1 0 12 0.0000 4 180 315 4500 4350 loop\001 --6 -6 4275 2550 5100 2850 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4275 2550 5100 2550 5100 2850 4275 2850 4275 2550 -4 0 0 50 -1 0 12 0.0000 4 135 450 4425 2775 ctrl i/f\001 --6 -6 6000 3900 7200 4425 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 3900 7200 3900 7200 4425 6000 4425 6000 3900 -4 0 0 50 -1 0 12 0.0000 4 135 600 6075 4125 EAPOL\001 -4 0 0 50 -1 0 12 0.0000 4 135 1065 6075 4350 state machine\001 --6 -6 2775 3150 4050 3450 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 2775 3150 4050 3150 4050 3450 2775 3450 2775 3150 -4 0 0 50 -1 0 12 0.0000 4 180 990 2925 3375 configuration\001 --6 -6 3450 1200 4575 1500 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3450 1200 4575 1200 4575 1500 3450 1500 3450 1200 -4 0 0 50 -1 0 12 0.0000 4 180 870 3600 1425 hostapd_cli\001 --6 -6 3525 7800 5775 8100 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3525 7800 5775 7800 5775 8100 3525 8100 3525 7800 -4 0 0 50 -1 0 12 0.0000 4 135 2145 3600 8025 kernel network device driver\001 --6 -6 4275 6000 5100 6300 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4275 6000 5100 6000 5100 6300 4275 6300 4275 6000 -4 0 0 50 -1 0 12 0.0000 4 135 630 4350 6225 driver i/f\001 --6 -6 8175 4725 9225 5025 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 4725 9225 4725 9225 5025 8175 5025 8175 4725 -4 0 0 50 -1 0 12 0.0000 4 135 735 8250 4950 EAP-TLS\001 --6 -6 9300 4725 10350 5025 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 4725 10350 4725 10350 5025 9300 5025 9300 4725 -4 0 0 50 -1 0 12 0.0000 4 135 810 9375 4950 EAP-MD5\001 --6 -6 8175 5100 9225 5400 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 5100 9225 5100 9225 5400 8175 5400 8175 5100 -4 0 0 50 -1 0 12 0.0000 4 135 885 8250 5325 EAP-PEAP\001 --6 -6 9300 5100 10350 5400 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 5100 10350 5100 10350 5400 9300 5400 9300 5100 -4 0 0 50 -1 0 12 0.0000 4 135 840 9375 5325 EAP-TTLS\001 --6 -6 8175 5475 9225 5775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 5475 9225 5475 9225 5775 8175 5775 8175 5475 -4 0 0 50 -1 0 12 0.0000 4 135 780 8250 5700 EAP-GTC\001 --6 -6 8175 5850 9225 6150 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 5850 9225 5850 9225 6150 8175 6150 8175 5850 -4 0 0 50 -1 0 12 0.0000 4 135 750 8250 6075 EAP-SIM\001 --6 -6 8175 6225 9225 6525 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 6225 9225 6225 9225 6525 8175 6525 8175 6225 -4 0 0 50 -1 0 12 0.0000 4 135 765 8250 6450 EAP-PSK\001 --6 -6 9300 5850 10350 6150 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 5850 10350 5850 10350 6150 9300 6150 9300 5850 -4 0 0 50 -1 0 12 0.0000 4 135 825 9375 6075 EAP-AKA\001 --6 -6 9300 5475 10350 5775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9300 5475 10350 5475 10350 5775 9300 5775 9300 5475 -4 0 0 50 -1 0 12 0.0000 4 135 795 9375 5700 EAP-PAX\001 --6 -6 8175 6600 9675 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8175 6600 9675 6600 9675 6900 8175 6900 8175 6600 -4 0 0 50 -1 0 12 0.0000 4 135 1365 8250 6825 EAP-MSCHAPv2\001 --6 -6 8700 3450 9375 3750 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8700 3450 9375 3450 9375 3750 8700 3750 8700 3450 -4 0 0 50 -1 0 12 0.0000 4 150 480 8775 3675 crypto\001 --6 -6 9600 3450 10275 3750 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9600 3450 10275 3450 10275 3750 9600 3750 9600 3450 -4 0 0 50 -1 0 12 0.0000 4 135 315 9750 3675 TLS\001 --6 -6 6000 5775 7200 6300 -6 6000 5775 7200 6300 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6000 5775 7200 5775 7200 6300 6000 6300 6000 5775 -4 0 0 50 -1 0 12 0.0000 4 135 690 6075 6000 RADIUS\001 --6 -4 0 0 50 -1 0 12 0.0000 4 90 480 6075 6225 server\001 --6 -6 8100 2250 8925 2775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8100 2250 8925 2250 8925 2775 8100 2775 8100 2250 -4 0 0 50 -1 0 12 0.0000 4 135 690 8175 2475 RADIUS\001 -4 0 0 50 -1 0 12 0.0000 4 135 420 8175 2700 client\001 --6 -6 3150 5475 4425 5775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3150 5475 4425 5475 4425 5775 3150 5775 3150 5475 -4 0 0 50 -1 0 12 0.0000 4 135 990 3300 5700 driver events\001 --6 -6 1950 5550 2625 6075 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1950 5550 2625 5550 2625 6075 1950 6075 1950 5550 -4 0 0 50 -1 0 12 0.0000 4 135 540 2025 5775 Station\001 -4 0 0 50 -1 0 12 0.0000 4 135 375 2025 6000 table\001 --6 -6 1875 4725 2925 5250 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1875 4725 2925 4725 2925 5250 1875 5250 1875 4725 -4 0 0 50 -1 0 12 0.0000 4 135 960 1950 4950 IEEE 802.11\001 -4 0 0 50 -1 0 12 0.0000 4 135 555 1950 5175 MLME\001 --6 -2 1 1 1 0 7 50 -1 -1 3.000 0 0 -1 0 0 2 - 1275 4200 1875 4200 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 4500 2550 3900 1500 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 4800 2550 5400 1500 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 2925 4200 4350 4200 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5025 3900 6000 3000 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5025 4200 6000 4200 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4650 6000 4650 4425 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6600 4425 6600 4950 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6600 3225 6600 3900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 5250 8100 5250 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 9075 4425 9075 3750 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 3000 8700 3525 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4650 3900 4650 2850 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 4125 8700 3675 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6000 4350 5025 6000 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6000 3150 4875 6000 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1500 2100 10800 2100 10800 7500 1500 7500 1500 2100 -2 1 0 1 2 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 9900 4425 9900 3750 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 1 - 4350 3900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4350 3900 4050 3450 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4350 4425 4050 5475 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 2250 7200 4200 7800 -2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2 - 7200 7200 5100 7800 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 2775 6900 3675 6900 3675 7200 2775 7200 2775 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 3750 6900 4650 6900 4650 7200 3750 7200 3750 6900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 - 2250 6900 2250 6600 7200 6600 7200 6900 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 3225 6900 3225 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4200 6900 4200 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5175 6900 5175 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6150 6900 6150 6600 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 4650 6600 4650 6300 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 1800 6900 2700 6900 2700 7200 1800 7200 1800 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 4725 6900 5625 6900 5625 7200 4725 7200 4725 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 5700 6900 6600 6900 6600 7200 5700 7200 5700 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 6675 6900 7800 6900 7800 7200 6675 7200 6675 6900 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 8100 6975 10425 6975 10425 4425 8100 4425 8100 6975 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 6600 5475 6600 5775 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5025 4425 6000 5775 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 - 4800 3900 5925 2550 8100 2550 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 7200 3900 8475 2775 -2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 - 9450 2250 10425 2250 10425 2775 9450 2775 9450 2250 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 8925 2475 9450 2475 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 2325 5550 2325 5250 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 2925 4950 4350 4275 -2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 3 - 2850 4725 5775 2400 8100 2400 -4 0 0 50 -1 0 12 0.0000 4 135 915 375 3975 EAPOL and\001 -4 0 0 50 -1 0 12 0.0000 4 180 630 375 4200 pre-auth\001 -4 0 0 50 -1 0 12 0.0000 4 180 810 375 4425 ethertypes\001 -4 0 0 50 -1 0 12 0.0000 4 135 1050 375 4650 from/to kernel\001 -4 0 0 50 -1 0 12 0.0000 4 135 1920 3675 1875 frontend control interface\001 -4 0 0 50 -1 2 14 0.0000 4 195 720 1637 2371 hostapd\001 -4 0 0 50 -1 0 12 0.0000 4 180 600 3825 7125 prism54\001 -4 0 0 50 -1 0 12 0.0000 4 180 510 1875 7125 hostap\001 -4 0 0 50 -1 0 12 0.0000 4 135 600 2850 7125 madwifi\001 -4 0 0 50 -1 0 12 0.0000 4 135 270 4800 7125 bsd\001 -4 0 0 50 -1 0 12 0.0000 4 105 300 6750 7125 test\001 -4 0 0 50 -1 0 12 0.0000 4 135 420 5775 7125 wired\001 -4 0 0 50 -1 0 12 0.0000 4 135 1050 8700 4650 EAP methods\001 -4 0 0 50 -1 0 12 0.0000 4 135 690 9525 2475 RADIUS\001 -4 0 0 50 -1 0 12 0.0000 4 180 825 9525 2700 accounting\001 diff --git a/contrib/wpa/hostapd/doc/kerneldoc2doxygen.pl b/contrib/wpa/hostapd/doc/kerneldoc2doxygen.pl deleted file mode 100755 index 68835a1ddd31..000000000000 --- a/contrib/wpa/hostapd/doc/kerneldoc2doxygen.pl +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/perl -w -# -########################################################################## -# Convert kernel-doc style comments to Doxygen comments. -########################################################################## -# -# This script reads a C source file from stdin, and writes -# to stdout. Normal usage: -# -# $ mv file.c file.c.gtkdoc -# $ kerneldoc2doxygen.pl file.c -# -# Or to do the same thing with multiple files: -# $ perl -i.gtkdoc kerneldoc2doxygen.pl *.c *.h -# -# This script may also be suitable for use as a Doxygen input filter, -# but that has not been tested. -# -# Back up your source files before using this script!! -# -########################################################################## -# Copyright (C) 2003 Jonathan Foster -# Copyright (C) 2005 Jouni Malinen -# (modified for kerneldoc format used in wpa_supplicant) -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# or look at http://www.gnu.org/licenses/gpl.html -########################################################################## - - -########################################################################## -# -# This function converts a single comment from gtk-doc to Doxygen format. -# The parameter does not include the opening or closing lines -# (i.e. given a comment like this: -# "/**\n" -# " * FunctionName:\n" -# " * @foo: This describes the foo parameter\n" -# " * @bar: This describes the bar parameter\n" -# " * @Returns: This describes the return value\n" -# " *\n" -# " * This describes the function.\n" -# " */\n" -# This function gets: -# " * FunctionName:\n" -# " * @foo: This describes the foo parameter\n" -# " * @bar: This describes the bar parameter\n" -# " * @Returns: This describes the return value\n" -# " *\n" -# " * This describes the function.\n" -# And it returns: -# " * This describes the function.\n" -# " *\n" -# " * @param foo This describes the foo parameter\n" -# " * @param bar This describes the bar parameter\n" -# " * @return This describes the return value\n" -# ) -# -sub fixcomment { - $t = $_[0]; - - # " * func: foo" --> "\brief foo\n" - # " * struct bar: foo" --> "\brief foo\n" - # If this fails, not a kernel-doc comment ==> return unmodified. - ($t =~ s/^[\t ]*\*[\t ]*(struct )?([^ \t\n]*) - ([^\n]*)/\\brief $3\n/s) - or return $t; - - # " * Returns: foo" --> "\return foo" - $t =~ s/\n[\t ]*\*[\t ]*Returns:/\n\\return/sig; - - # " * @foo: bar" --> "\param foo bar" - # Handle two common typos: No ":", or "," instead of ":". - $t =~ s/\n[\t ]*\*[\t ]*\@([^ :,]*)[:,]?[\t ]*/\n\\param $1 /sg; - - return $t; -} - -########################################################################## -# Start of main code - -# Read entire stdin into memory - one multi-line string. -$_ = do { local $/; <> }; - -s{^/\*\n \*}{/\*\* \\file\n\\brief}; -s{ \* Copyright}{\\par Copyright\nCopyright}; - -# Fix any comments like "/*************" so they don't match. -# "/***" ===> "/* *" -s{/\*\*\*}{/\* \*}gs; - -# The main comment-detection code. -s{ - ( # $1 = Open comment - /\*\* # Open comment - (?!\*) # Do not match /*** (redundant due to fixup above). - [\t ]*\n? # If 1st line is whitespace, match the lot (including the newline). - ) - (.*?) # $2 = Body of comment (multi-line) - ( # $3 = Close comment - ( # If possible, match the whitespace before the close-comment - (?<=\n) # This part only matches after a newline - [\t ]* # Eat whitespace - )? - \*/ # Close comment - ) - } - { - $1 . fixcomment($2) . $3 - }gesx; -# ^^^^ Modes: g - Global, match all occurances. -# e - Evaluate the replacement as an expression. -# s - Single-line - allows the pattern to match across newlines. -# x - eXtended pattern, ignore embedded whitespace -# and allow comments. - -# Write results to stdout -print $_; - diff --git a/contrib/wpa/hostapd/doc/mainpage.doxygen b/contrib/wpa/hostapd/doc/mainpage.doxygen deleted file mode 100644 index 7cf95de584af..000000000000 --- a/contrib/wpa/hostapd/doc/mainpage.doxygen +++ /dev/null @@ -1,52 +0,0 @@ -/** -\mainpage Developers' documentation for hostapd - -hostapd includes IEEE 802.11 access point management (authentication / -association), IEEE 802.1X/WPA/WPA2 Authenticator, EAP server, and -RADIUS authentication server functionality. It can be build with -various configuration option, e.g., a standalone AP management -solution or a RADIUS authentication server with support for number of -EAP methods. - -The goal of this documentation and comments in the source code is to -give enough information for other developers to understand how hostapd -has been implemented, how it can be modified, how new drivers can be -supported, and how hostapd can be ported to other operating -systems. If any information is missing, feel free to contact Jouni -Malinen for more information. Contributions as -patch files are also very welcome at the same address. Please note -that hostapd is licensed under dual license, GPLv2 or BSD at user's -choice. All contributions to hostapd are expected to use compatible -licensing terms. - -The source code and read-only access to hostapd CVS repository -is available from the project home page at -http://hostap.epitest.fi/hostapd/. This developers' documentation -is also available as a PDF file from -http://hostap.epitest.fi/hostapd/hostapd-devel.pdf . - -The design goal for hostapd was to use hardware, driver, and -OS independent, portable C code for all WPA functionality. The source -code is divided into separate C files as shown on the \ref -code_structure "code structure page". All hardware/driver specific -functionality is in separate files that implement a \ref -driver_wrapper "well-defined driver API". Information about porting -to different target boards and operating systems is available on -the \ref porting "porting page". - -EAPOL (IEEE 802.1X) state machines are implemented as a separate -module that interacts with \ref eap_module "EAP server implementation". -Similarly, RADIUS authentication server is in its own separate module. -Both IEEE 802.1X and RADIUS authentication server can use EAP server -functionality. - -hostapd implements a \ref ctrl_iface_page "control interface" that can -be used by external programs to control the operations of the hostapdt -daemon and to get status information and event notifications. There is -a small C library that provides helper functions to facilitate the use -of the control interface. This library can also be used with C++. - -\image html hostapd.png "hostapd modules" -\image latex hostapd.eps "hostapd modules" width=15cm - -*/ diff --git a/contrib/wpa/hostapd/doc/porting.doxygen b/contrib/wpa/hostapd/doc/porting.doxygen deleted file mode 100644 index 0621791c0be0..000000000000 --- a/contrib/wpa/hostapd/doc/porting.doxygen +++ /dev/null @@ -1,5 +0,0 @@ -/** -\page porting Porting to different target boards and operating systems - - -*/ diff --git a/contrib/wpa/hostapd/driver.h b/contrib/wpa/hostapd/driver.h deleted file mode 100644 index 45f546087302..000000000000 --- a/contrib/wpa/hostapd/driver.h +++ /dev/null @@ -1,798 +0,0 @@ -/* - * hostapd - driver interface definition - * Copyright (c) 2002-2007, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef DRIVER_H -#define DRIVER_H - -struct hostapd_sta_add_params { - const u8 *addr; - u16 aid; - u16 capability; - const u8 *supp_rates; - size_t supp_rates_len; - int flags; - u16 listen_interval; - const struct ht_cap_ie *ht_capabilities; -}; - -struct hostapd_freq_params { - int mode; - int freq; - int ht_enabled; - int sec_channel_offset; /* 0 = HT40 disabled, -1 = HT40 enabled, - * secondary channel below primary, 1 = HT40 - * enabled, secondary channel above primary */ -}; - -enum hostapd_driver_if_type { - HOSTAPD_IF_VLAN, HOSTAPD_IF_WDS -}; - -struct wpa_driver_ops { - const char *name; /* as appears in the config file */ - - void * (*init)(struct hostapd_data *hapd); - void * (*init_bssid)(struct hostapd_data *hapd, const u8 *bssid); - void (*deinit)(void *priv); - - int (*wireless_event_init)(void *priv); - void (*wireless_event_deinit)(void *priv); - - /** - * set_8021x - enable/disable IEEE 802.1X support - * @ifname: Interface name (for multi-SSID/VLAN support) - * @priv: driver private data - * @enabled: 1 = enable, 0 = disable - * - * Returns: 0 on success, -1 on failure - * - * Configure the kernel driver to enable/disable 802.1X support. - * This may be an empty function if 802.1X support is always enabled. - */ - int (*set_ieee8021x)(const char *ifname, void *priv, int enabled); - - /** - * set_privacy - enable/disable privacy - * @priv: driver private data - * @enabled: 1 = privacy enabled, 0 = disabled - * - * Return: 0 on success, -1 on failure - * - * Configure privacy. - */ - int (*set_privacy)(const char *ifname, void *priv, int enabled); - - int (*set_encryption)(const char *ifname, void *priv, const char *alg, - const u8 *addr, int idx, - const u8 *key, size_t key_len, int txkey); - int (*get_seqnum)(const char *ifname, void *priv, const u8 *addr, - int idx, u8 *seq); - int (*get_seqnum_igtk)(const char *ifname, void *priv, const u8 *addr, - int idx, u8 *seq); - int (*flush)(void *priv); - int (*set_generic_elem)(const char *ifname, void *priv, const u8 *elem, - size_t elem_len); - - int (*read_sta_data)(void *priv, struct hostap_sta_driver_data *data, - const u8 *addr); - int (*send_eapol)(void *priv, const u8 *addr, const u8 *data, - size_t data_len, int encrypt, const u8 *own_addr); - int (*sta_deauth)(void *priv, const u8 *addr, int reason); - int (*sta_disassoc)(void *priv, const u8 *addr, int reason); - int (*sta_remove)(void *priv, const u8 *addr); - int (*get_ssid)(const char *ifname, void *priv, u8 *buf, int len); - int (*set_ssid)(const char *ifname, void *priv, const u8 *buf, - int len); - int (*set_countermeasures)(void *priv, int enabled); - int (*send_mgmt_frame)(void *priv, const void *msg, size_t len, - int flags); - int (*set_assoc_ap)(void *priv, const u8 *addr); - /* note: sta_add() is deprecated; use sta_add2() instead */ - int (*sta_add)(const char *ifname, void *priv, const u8 *addr, u16 aid, - u16 capability, u8 *supp_rates, size_t supp_rates_len, - int flags, u16 listen_interval); - int (*sta_add2)(const char *ifname, void *priv, - struct hostapd_sta_add_params *params); - int (*get_inact_sec)(void *priv, const u8 *addr); - int (*sta_clear_stats)(void *priv, const u8 *addr); - - /* note: set_freq() is deprecated; use set_freq2() instead */ - int (*set_freq)(void *priv, int mode, int freq); - int (*set_freq2)(void *priv, struct hostapd_freq_params *freq); - int (*set_rts)(void *priv, int rts); - int (*get_rts)(void *priv, int *rts); - int (*set_frag)(void *priv, int frag); - int (*get_frag)(void *priv, int *frag); - int (*set_retry)(void *priv, int short_retry, int long_retry); - int (*get_retry)(void *priv, int *short_retry, int *long_retry); - - int (*sta_set_flags)(void *priv, const u8 *addr, - int total_flags, int flags_or, int flags_and); - int (*set_rate_sets)(void *priv, int *supp_rates, int *basic_rates, - int mode); - int (*set_regulatory_domain)(void *priv, unsigned int rd); - int (*set_country)(void *priv, const char *country); - int (*set_ieee80211d)(void *priv, int enabled); - int (*set_beacon)(const char *ifname, void *priv, - u8 *head, size_t head_len, - u8 *tail, size_t tail_len); - - /* Configure internal bridge: - * 0 = disabled, i.e., client separation is enabled (no bridging of - * packets between associated STAs - * 1 = enabled, i.e., bridge packets between associated STAs (default) - */ - int (*set_internal_bridge)(void *priv, int value); - int (*set_beacon_int)(void *priv, int value); - int (*set_dtim_period)(const char *ifname, void *priv, int value); - /* Configure broadcast SSID mode: - * 0 = include SSID in Beacon frames and reply to Probe Request frames - * that use broadcast SSID - * 1 = hide SSID from Beacon frames and ignore Probe Request frames for - * broadcast SSID - */ - int (*set_broadcast_ssid)(void *priv, int value); - int (*set_cts_protect)(void *priv, int value); - int (*set_key_tx_rx_threshold)(void *priv, int value); - int (*set_preamble)(void *priv, int value); - int (*set_short_slot_time)(void *priv, int value); - int (*set_tx_queue_params)(void *priv, int queue, int aifs, int cw_min, - int cw_max, int burst_time); - int (*bss_add)(void *priv, const char *ifname, const u8 *bssid); - int (*bss_remove)(void *priv, const char *ifname); - int (*valid_bss_mask)(void *priv, const u8 *addr, const u8 *mask); - int (*passive_scan)(void *priv, int now, int our_mode_only, - int interval, int _listen, int *channel, - int *last_rx); - struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv, - u16 *num_modes, - u16 *flags); - int (*if_add)(const char *iface, void *priv, - enum hostapd_driver_if_type type, char *ifname, - const u8 *addr); - int (*if_update)(void *priv, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr); - int (*if_remove)(void *priv, enum hostapd_driver_if_type type, - const char *ifname, const u8 *addr); - int (*set_sta_vlan)(void *priv, const u8 *addr, const char *ifname, - int vlan_id); - /** - * commit - Optional commit changes handler - * @priv: driver private data - * Returns: 0 on success, -1 on failure - * - * This optional handler function can be registered if the driver - * interface implementation needs to commit changes (e.g., by setting - * network interface up) at the end of initial configuration. If set, - * this handler will be called after initial setup has been completed. - */ - int (*commit)(void *priv); - - int (*send_ether)(void *priv, const u8 *dst, const u8 *src, u16 proto, - const u8 *data, size_t data_len); - - int (*set_radius_acl_auth)(void *priv, const u8 *mac, int accepted, - u32 session_timeout); - int (*set_radius_acl_expire)(void *priv, const u8 *mac); - - int (*set_ht_params)(const char *ifname, void *priv, - const u8 *ht_capab, size_t ht_capab_len, - const u8 *ht_oper, size_t ht_oper_len); - - int (*set_wps_beacon_ie)(const char *ifname, void *priv, - const u8 *ie, size_t len); - int (*set_wps_probe_resp_ie)(const char *ifname, void *priv, - const u8 *ie, size_t len); -}; - -static inline void * -hostapd_driver_init(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->init == NULL) - return NULL; - return hapd->driver->init(hapd); -} - -static inline void * -hostapd_driver_init_bssid(struct hostapd_data *hapd, const u8 *bssid) -{ - if (hapd->driver == NULL || hapd->driver->init_bssid == NULL) - return NULL; - return hapd->driver->init_bssid(hapd, bssid); -} - -static inline void -hostapd_driver_deinit(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->deinit == NULL) - return; - hapd->driver->deinit(hapd->drv_priv); -} - -static inline int -hostapd_wireless_event_init(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || - hapd->driver->wireless_event_init == NULL) - return 0; - return hapd->driver->wireless_event_init(hapd->drv_priv); -} - -static inline void -hostapd_wireless_event_deinit(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || - hapd->driver->wireless_event_deinit == NULL) - return; - hapd->driver->wireless_event_deinit(hapd->drv_priv); -} - -static inline int -hostapd_set_ieee8021x(const char *ifname, struct hostapd_data *hapd, - int enabled) -{ - if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL) - return 0; - return hapd->driver->set_ieee8021x(ifname, hapd->drv_priv, enabled); -} - -static inline int -hostapd_set_privacy(struct hostapd_data *hapd, int enabled) -{ - if (hapd->driver == NULL || hapd->driver->set_privacy == NULL) - return 0; - return hapd->driver->set_privacy(hapd->conf->iface, hapd->drv_priv, - enabled); -} - -static inline int -hostapd_set_encryption(const char *ifname, struct hostapd_data *hapd, - const char *alg, const u8 *addr, int idx, - u8 *key, size_t key_len, int txkey) -{ - if (hapd->driver == NULL || hapd->driver->set_encryption == NULL) - return 0; - return hapd->driver->set_encryption(ifname, hapd->drv_priv, alg, addr, - idx, key, key_len, txkey); -} - -static inline int -hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd, - const u8 *addr, int idx, u8 *seq) -{ - if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL) - return 0; - return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx, - seq); -} - -static inline int -hostapd_get_seqnum_igtk(const char *ifname, struct hostapd_data *hapd, - const u8 *addr, int idx, u8 *seq) -{ - if (hapd->driver == NULL || hapd->driver->get_seqnum_igtk == NULL) - return -1; - return hapd->driver->get_seqnum_igtk(ifname, hapd->drv_priv, addr, idx, - seq); -} - -static inline int -hostapd_flush(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->flush == NULL) - return 0; - return hapd->driver->flush(hapd->drv_priv); -} - -static inline int -hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, - size_t elem_len) -{ - if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL) - return 0; - return hapd->driver->set_generic_elem(hapd->conf->iface, - hapd->drv_priv, elem, elem_len); -} - -static inline int -hostapd_read_sta_data(struct hostapd_data *hapd, - struct hostap_sta_driver_data *data, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL) - return -1; - return hapd->driver->read_sta_data(hapd->drv_priv, data, addr); -} - -static inline int -hostapd_send_eapol(struct hostapd_data *hapd, const u8 *addr, const u8 *data, - size_t data_len, int encrypt) -{ - if (hapd->driver == NULL || hapd->driver->send_eapol == NULL) - return 0; - return hapd->driver->send_eapol(hapd->drv_priv, addr, data, data_len, - encrypt, hapd->own_addr); -} - -static inline int -hostapd_sta_deauth(struct hostapd_data *hapd, const u8 *addr, int reason) -{ - if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL) - return 0; - return hapd->driver->sta_deauth(hapd->drv_priv, addr, reason); -} - -static inline int -hostapd_sta_disassoc(struct hostapd_data *hapd, const u8 *addr, int reason) -{ - if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL) - return 0; - return hapd->driver->sta_disassoc(hapd->drv_priv, addr, reason); -} - -static inline int -hostapd_sta_remove(struct hostapd_data *hapd, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->sta_remove == NULL) - return 0; - return hapd->driver->sta_remove(hapd->drv_priv, addr); -} - -static inline int -hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len) -{ - if (hapd->driver == NULL || hapd->driver->get_ssid == NULL) - return 0; - return hapd->driver->get_ssid(hapd->conf->iface, hapd->drv_priv, buf, - len); -} - -static inline int -hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len) -{ - if (hapd->driver == NULL || hapd->driver->set_ssid == NULL) - return 0; - return hapd->driver->set_ssid(hapd->conf->iface, hapd->drv_priv, buf, - len); -} - -static inline int -hostapd_send_mgmt_frame(struct hostapd_data *hapd, const void *msg, size_t len, - int flags) -{ - if (hapd->driver == NULL || hapd->driver->send_mgmt_frame == NULL) - return 0; - return hapd->driver->send_mgmt_frame(hapd->drv_priv, msg, len, flags); -} - -static inline int -hostapd_set_assoc_ap(struct hostapd_data *hapd, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->set_assoc_ap == NULL) - return 0; - return hapd->driver->set_assoc_ap(hapd->drv_priv, addr); -} - -static inline int -hostapd_set_countermeasures(struct hostapd_data *hapd, int enabled) -{ - if (hapd->driver == NULL || hapd->driver->set_countermeasures == NULL) - return 0; - return hapd->driver->set_countermeasures(hapd->drv_priv, enabled); -} - -static inline int -hostapd_sta_add(const char *ifname, struct hostapd_data *hapd, const u8 *addr, - u16 aid, u16 capability, const u8 *supp_rates, - size_t supp_rates_len, int flags, u16 listen_interval, - const struct ht_cap_ie *ht_capabilities) -{ - if (hapd->driver == NULL) - return 0; - - if (hapd->driver->sta_add2) { - struct hostapd_sta_add_params params; - os_memset(¶ms, 0, sizeof(params)); - params.addr = addr; - params.aid = aid; - params.capability = capability; - params.supp_rates = supp_rates; - params.supp_rates_len = supp_rates_len; - params.flags = flags; - params.listen_interval = listen_interval; - params.ht_capabilities = ht_capabilities; - return hapd->driver->sta_add2(ifname, hapd->drv_priv, ¶ms); - } - - if (hapd->driver->sta_add == NULL) - return 0; - return hapd->driver->sta_add(ifname, hapd->drv_priv, addr, aid, - capability, (u8 *) supp_rates, - supp_rates_len, - flags, listen_interval); -} - -static inline int -hostapd_get_inact_sec(struct hostapd_data *hapd, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL) - return 0; - return hapd->driver->get_inact_sec(hapd->drv_priv, addr); -} - -static inline int -hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq, int ht_enabled, - int sec_channel_offset) -{ - if (hapd->driver == NULL) - return 0; - if (hapd->driver->set_freq2) { - struct hostapd_freq_params data; - os_memset(&data, 0, sizeof(data)); - data.mode = mode; - data.freq = freq; - data.ht_enabled = ht_enabled; - data.sec_channel_offset = sec_channel_offset; - return hapd->driver->set_freq2(hapd->drv_priv, &data); - } - - if (hapd->driver->set_freq == NULL) - return 0; - return hapd->driver->set_freq(hapd->drv_priv, mode, freq); -} - -static inline int -hostapd_set_rts(struct hostapd_data *hapd, int rts) -{ - if (hapd->driver == NULL || hapd->driver->set_rts == NULL) - return 0; - return hapd->driver->set_rts(hapd->drv_priv, rts); -} - -static inline int -hostapd_get_rts(struct hostapd_data *hapd, int *rts) -{ - if (hapd->driver == NULL || hapd->driver->get_rts == NULL) - return 0; - return hapd->driver->get_rts(hapd->drv_priv, rts); -} - -static inline int -hostapd_set_frag(struct hostapd_data *hapd, int frag) -{ - if (hapd->driver == NULL || hapd->driver->set_frag == NULL) - return 0; - return hapd->driver->set_frag(hapd->drv_priv, frag); -} - -static inline int -hostapd_get_frag(struct hostapd_data *hapd, int *frag) -{ - if (hapd->driver == NULL || hapd->driver->get_frag == NULL) - return 0; - return hapd->driver->get_frag(hapd->drv_priv, frag); -} - -static inline int -hostapd_set_retry(struct hostapd_data *hapd, int short_retry, int long_retry) -{ - if (hapd->driver == NULL || hapd->driver->set_retry == NULL) - return 0; - return hapd->driver->set_retry(hapd->drv_priv, short_retry, - long_retry); -} - -static inline int -hostapd_get_retry(struct hostapd_data *hapd, int *short_retry, int *long_retry) -{ - if (hapd->driver == NULL || hapd->driver->get_retry == NULL) - return 0; - return hapd->driver->get_retry(hapd->drv_priv, short_retry, - long_retry); -} - -static inline int -hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, - int total_flags, int flags_or, int flags_and) -{ - if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL) - return 0; - return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags, - flags_or, flags_and); -} - -static inline int -hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates, - int *basic_rates, int mode) -{ - if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL) - return 0; - return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates, - basic_rates, mode); -} - -static inline int -hostapd_set_regulatory_domain(struct hostapd_data *hapd, unsigned int rd) -{ - if (hapd->driver == NULL || - hapd->driver->set_regulatory_domain == NULL) - return 0; - return hapd->driver->set_regulatory_domain(hapd->drv_priv, rd); -} - -static inline int -hostapd_set_country(struct hostapd_data *hapd, const char *country) -{ - if (hapd->driver == NULL || - hapd->driver->set_country == NULL) - return 0; - return hapd->driver->set_country(hapd->drv_priv, country); -} - -static inline int -hostapd_set_ieee80211d(struct hostapd_data *hapd, int enabled) -{ - if (hapd->driver == NULL || - hapd->driver->set_ieee80211d == NULL) - return 0; - return hapd->driver->set_ieee80211d(hapd->drv_priv, enabled); -} - -static inline int -hostapd_sta_clear_stats(struct hostapd_data *hapd, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL) - return 0; - return hapd->driver->sta_clear_stats(hapd->drv_priv, addr); -} - -static inline int -hostapd_set_beacon(const char *ifname, struct hostapd_data *hapd, - u8 *head, size_t head_len, - u8 *tail, size_t tail_len) -{ - if (hapd->driver == NULL || hapd->driver->set_beacon == NULL) - return 0; - return hapd->driver->set_beacon(ifname, hapd->drv_priv, head, head_len, - tail, tail_len); -} - -static inline int -hostapd_set_internal_bridge(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_internal_bridge == NULL) - return 0; - return hapd->driver->set_internal_bridge(hapd->drv_priv, value); -} - -static inline int -hostapd_set_beacon_int(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_beacon_int == NULL) - return 0; - return hapd->driver->set_beacon_int(hapd->drv_priv, value); -} - -static inline int -hostapd_set_dtim_period(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_dtim_period == NULL) - return 0; - return hapd->driver->set_dtim_period(hapd->conf->iface, hapd->drv_priv, - value); -} - -static inline int -hostapd_set_broadcast_ssid(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_broadcast_ssid == NULL) - return 0; - return hapd->driver->set_broadcast_ssid(hapd->drv_priv, value); -} - -static inline int -hostapd_set_cts_protect(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL) - return 0; - return hapd->driver->set_cts_protect(hapd->drv_priv, value); -} - -static inline int -hostapd_set_key_tx_rx_threshold(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || - hapd->driver->set_key_tx_rx_threshold == NULL) - return 0; - return hapd->driver->set_key_tx_rx_threshold(hapd->drv_priv, value); -} - -static inline int -hostapd_set_preamble(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_preamble == NULL) - return 0; - return hapd->driver->set_preamble(hapd->drv_priv, value); -} - -static inline int -hostapd_set_short_slot_time(struct hostapd_data *hapd, int value) -{ - if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL) - return 0; - return hapd->driver->set_short_slot_time(hapd->drv_priv, value); -} - -static inline int -hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, - int cw_min, int cw_max, int burst_time) -{ - if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL) - return 0; - return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs, - cw_min, cw_max, burst_time); -} - -static inline int -hostapd_bss_add(struct hostapd_data *hapd, const char *ifname, const u8 *bssid) -{ - if (hapd->driver == NULL || hapd->driver->bss_add == NULL) - return 0; - return hapd->driver->bss_add(hapd->drv_priv, ifname, bssid); -} - -static inline int -hostapd_bss_remove(struct hostapd_data *hapd, const char *ifname) -{ - if (hapd->driver == NULL || hapd->driver->bss_remove == NULL) - return 0; - return hapd->driver->bss_remove(hapd->drv_priv, ifname); -} - -static inline int -hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr, - const u8 *mask) -{ - if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL) - return 1; - return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask); -} - -static inline int -hostapd_if_add(struct hostapd_data *hapd, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->if_add == NULL) - return -1; - return hapd->driver->if_add(hapd->conf->iface, hapd->drv_priv, type, - ifname, addr); -} - -static inline int -hostapd_if_update(struct hostapd_data *hapd, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->if_update == NULL) - return -1; - return hapd->driver->if_update(hapd->drv_priv, type, ifname, addr); -} - -static inline int -hostapd_if_remove(struct hostapd_data *hapd, enum hostapd_driver_if_type type, - char *ifname, const u8 *addr) -{ - if (hapd->driver == NULL || hapd->driver->if_remove == NULL) - return -1; - return hapd->driver->if_remove(hapd->drv_priv, type, ifname, addr); -} - -static inline int -hostapd_passive_scan(struct hostapd_data *hapd, int now, int our_mode_only, - int interval, int _listen, int *channel, - int *last_rx) -{ - if (hapd->driver == NULL || hapd->driver->passive_scan == NULL) - return -1; - return hapd->driver->passive_scan(hapd->drv_priv, now, our_mode_only, - interval, _listen, channel, last_rx); -} - -static inline struct hostapd_hw_modes * -hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, - u16 *flags) -{ - if (hapd->driver == NULL || hapd->driver->get_hw_feature_data == NULL) - return NULL; - return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes, - flags); -} - -static inline int -hostapd_set_sta_vlan(const char *ifname, struct hostapd_data *hapd, - const u8 *addr, int vlan_id) -{ - if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL) - return 0; - return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname, vlan_id); -} - -static inline int -hostapd_driver_commit(struct hostapd_data *hapd) -{ - if (hapd->driver == NULL || hapd->driver->commit == NULL) - return 0; - return hapd->driver->commit(hapd->drv_priv); -} - -static inline int -hostapd_set_radius_acl_auth(struct hostapd_data *hapd, const u8 *mac, - int accepted, u32 session_timeout) -{ - if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL) - return 0; - return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted, - session_timeout); -} - -static inline int -hostapd_set_radius_acl_expire(struct hostapd_data *hapd, const u8 *mac) -{ - if (hapd->driver == NULL || - hapd->driver->set_radius_acl_expire == NULL) - return 0; - return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac); -} - -#ifdef CONFIG_IEEE80211N -static inline int -hostapd_set_ht_params(const char *ifname, struct hostapd_data *hapd, - const u8 *ht_capab, size_t ht_capab_len, - const u8 *ht_oper, size_t ht_oper_len) -{ - if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL || - ht_capab == NULL || ht_oper == NULL) - return 0; - return hapd->driver->set_ht_params( - ifname, hapd->drv_priv, ht_capab, ht_capab_len, - ht_oper, ht_oper_len); -} -#endif /* CONFIG_IEEE80211N */ - -static inline int -hostapd_drv_none(struct hostapd_data *hapd) -{ - return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0; -} - -static inline int -hostapd_set_wps_beacon_ie(struct hostapd_data *hapd, const u8 *ie, size_t len) -{ - if (hapd->driver == NULL || hapd->driver->set_wps_beacon_ie == NULL) - return 0; - return hapd->driver->set_wps_beacon_ie(hapd->conf->iface, - hapd->drv_priv, ie, len); -} - -static inline int -hostapd_set_wps_probe_resp_ie(struct hostapd_data *hapd, const u8 *ie, - size_t len) -{ - if (hapd->driver == NULL || - hapd->driver->set_wps_probe_resp_ie == NULL) - return 0; - return hapd->driver->set_wps_probe_resp_ie(hapd->conf->iface, - hapd->drv_priv, ie, len); -} - -#endif /* DRIVER_H */ diff --git a/contrib/wpa/hostapd/driver_bsd.c b/contrib/wpa/hostapd/driver_bsd.c deleted file mode 100644 index 43d57d9091d3..000000000000 --- a/contrib/wpa/hostapd/driver_bsd.c +++ /dev/null @@ -1,839 +0,0 @@ -/* - * hostapd / Driver interaction with BSD net80211 layer - * Copyright (c) 2004, Sam Leffler - * Copyright (c) 2004, 2Wire, Inc - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#include - -#include -#include -#include - -/* - * Avoid conflicts with hostapd definitions by undefining couple of defines - * from net80211 header files. - */ -#undef RSN_VERSION -#undef WPA_VERSION -#undef WPA_OUI_TYPE -#undef WME_OUI_TYPE - -#include "hostapd.h" -#include "driver.h" -#include "ieee802_1x.h" -#include "eloop.h" -#include "sta_info.h" -#include "l2_packet/l2_packet.h" - -#include "eapol_sm.h" -#include "wpa.h" -#include "radius/radius.h" -#include "ieee802_11.h" -#include "common.h" - -struct bsd_driver_data { - struct hostapd_data *hapd; /* back pointer */ - - char iface[IFNAMSIZ + 1]; - struct l2_packet_data *sock_xmit; /* raw packet xmit socket */ - int ioctl_sock; /* socket for ioctl() use */ - int wext_sock; /* socket for wireless events */ -}; - -static int bsd_sta_deauth(void *priv, const u8 *addr, int reason_code); - -static int -set80211var(struct bsd_driver_data *drv, int op, const void *arg, int arg_len) -{ - struct ieee80211req ireq; - - memset(&ireq, 0, sizeof(ireq)); - os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ); - ireq.i_type = op; - ireq.i_len = arg_len; - ireq.i_data = (void *) arg; - - if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) { - perror("ioctl[SIOCS80211]"); - return -1; - } - return 0; -} - -static int -get80211var(struct bsd_driver_data *drv, int op, void *arg, int arg_len) -{ - struct ieee80211req ireq; - - memset(&ireq, 0, sizeof(ireq)); - os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ); - ireq.i_type = op; - ireq.i_len = arg_len; - ireq.i_data = arg; - - if (ioctl(drv->ioctl_sock, SIOCG80211, &ireq) < 0) { - perror("ioctl[SIOCG80211]"); - return -1; - } - return ireq.i_len; -} - -static int -set80211param(struct bsd_driver_data *drv, int op, int arg) -{ - struct ieee80211req ireq; - - memset(&ireq, 0, sizeof(ireq)); - os_strlcpy(ireq.i_name, drv->iface, IFNAMSIZ); - ireq.i_type = op; - ireq.i_val = arg; - - if (ioctl(drv->ioctl_sock, SIOCS80211, &ireq) < 0) { - perror("ioctl[SIOCS80211]"); - return -1; - } - return 0; -} - -static const char * -ether_sprintf(const u8 *addr) -{ - static char buf[sizeof(MACSTR)]; - - if (addr != NULL) - snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); - else - snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0); - return buf; -} - -/* - * Configure WPA parameters. - */ -static int -bsd_configure_wpa(struct bsd_driver_data *drv) -{ - static const char *ciphernames[] = - { "WEP", "TKIP", "AES-OCB", "AES-CCM", "CKIP", "NONE" }; - struct hostapd_data *hapd = drv->hapd; - struct hostapd_bss_config *conf = hapd->conf; - int v; - - switch (conf->wpa_group) { - case WPA_CIPHER_CCMP: - v = IEEE80211_CIPHER_AES_CCM; - break; - case WPA_CIPHER_TKIP: - v = IEEE80211_CIPHER_TKIP; - break; - case WPA_CIPHER_WEP104: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_WEP40: - v = IEEE80211_CIPHER_WEP; - break; - case WPA_CIPHER_NONE: - v = IEEE80211_CIPHER_NONE; - break; - default: - printf("Unknown group key cipher %u\n", - conf->wpa_group); - return -1; - } - wpa_printf(MSG_DEBUG, "%s: group key cipher=%s (%u)", - __func__, ciphernames[v], v); - if (set80211param(drv, IEEE80211_IOC_MCASTCIPHER, v)) { - printf("Unable to set group key cipher to %u (%s)\n", - v, ciphernames[v]); - return -1; - } - if (v == IEEE80211_CIPHER_WEP) { - /* key length is done only for specific ciphers */ - v = (conf->wpa_group == WPA_CIPHER_WEP104 ? 13 : 5); - if (set80211param(drv, IEEE80211_IOC_MCASTKEYLEN, v)) { - printf("Unable to set group key length to %u\n", v); - return -1; - } - } - - v = 0; - if (conf->wpa_pairwise & WPA_CIPHER_CCMP) - v |= 1< wpa_pairwise & WPA_CIPHER_TKIP) - v |= 1< wpa_pairwise & WPA_CIPHER_NONE) - v |= 1< wpa_key_mgmt); - if (set80211param(drv, IEEE80211_IOC_KEYMGTALGS, conf->wpa_key_mgmt)) { - printf("Unable to set key management algorithms to 0x%x\n", - conf->wpa_key_mgmt); - return -1; - } - - v = 0; - if (conf->rsn_preauth) - v |= BIT(0); - wpa_printf(MSG_DEBUG, "%s: rsn capabilities=0x%x", - __func__, conf->rsn_preauth); - if (set80211param(drv, IEEE80211_IOC_RSNCAPS, v)) { - printf("Unable to set RSN capabilities to 0x%x\n", v); - return -1; - } - - wpa_printf(MSG_DEBUG, "%s: enable WPA= 0x%x", __func__, conf->wpa); - if (set80211param(drv, IEEE80211_IOC_WPA, conf->wpa)) { - printf("Unable to set WPA to %u\n", conf->wpa); - return -1; - } - return 0; -} - - -static int -bsd_set_iface_flags(void *priv, int dev_up) -{ - struct bsd_driver_data *drv = priv; - struct ifreq ifr; - - wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up); - - if (drv->ioctl_sock < 0) - return -1; - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ); - - if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCGIFFLAGS]"); - return -1; - } - - if (dev_up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); - return -1; - } - - if (dev_up) { - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ); - ifr.ifr_mtu = HOSTAPD_MTU; - if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) { - perror("ioctl[SIOCSIFMTU]"); - printf("Setting MTU failed - trying to survive with " - "current value\n"); - } - } - - return 0; -} - -static int -bsd_set_ieee8021x(const char *ifname, void *priv, int enabled) -{ - struct bsd_driver_data *drv = priv; - struct hostapd_data *hapd = drv->hapd; - struct hostapd_bss_config *conf = hapd->conf; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - - if (!enabled) { - /* XXX restore state */ - return set80211param(priv, IEEE80211_IOC_AUTHMODE, - IEEE80211_AUTH_AUTO); - } - if (!conf->wpa && !conf->ieee802_1x) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!"); - return -1; - } - if (conf->wpa && bsd_configure_wpa(drv) != 0) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "Error configuring WPA state!"); - return -1; - } - if (set80211param(priv, IEEE80211_IOC_AUTHMODE, - (conf->wpa ? IEEE80211_AUTH_WPA : IEEE80211_AUTH_8021X))) { - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, - HOSTAPD_LEVEL_WARNING, "Error enabling WPA/802.1X!"); - return -1; - } - return bsd_set_iface_flags(priv, 1); -} - -static int -bsd_set_privacy(const char *ifname, void *priv, int enabled) -{ - struct bsd_driver_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled); - - return set80211param(drv, IEEE80211_IOC_PRIVACY, enabled); -} - -static int -bsd_set_sta_authorized(void *priv, const u8 *addr, int authorized) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - - wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d", - __func__, ether_sprintf(addr), authorized); - - if (authorized) - mlme.im_op = IEEE80211_MLME_AUTHORIZE; - else - mlme.im_op = IEEE80211_MLME_UNAUTHORIZE; - mlme.im_reason = 0; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); -} - -static int -bsd_sta_set_flags(void *priv, const u8 *addr, int total_flags, int flags_or, - int flags_and) -{ - /* For now, only support setting Authorized flag */ - if (flags_or & WLAN_STA_AUTHORIZED) - return bsd_set_sta_authorized(priv, addr, 1); - if (!(flags_and & WLAN_STA_AUTHORIZED)) - return bsd_set_sta_authorized(priv, addr, 0); - return 0; -} - -static int -bsd_del_key(void *priv, const u8 *addr, int key_idx) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_del_key wk; - - wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d", - __func__, ether_sprintf(addr), key_idx); - - memset(&wk, 0, sizeof(wk)); - if (addr != NULL) { - memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); - wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */ - } else { - wk.idk_keyix = key_idx; - } - - return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk)); -} - -static int -bsd_set_key(const char *ifname, void *priv, const char *alg, - const u8 *addr, int key_idx, - const u8 *key, size_t key_len, int txkey) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_key wk; - u_int8_t cipher; - - if (strcmp(alg, "none") == 0) - return bsd_del_key(drv, addr, key_idx); - - wpa_printf(MSG_DEBUG, "%s: alg=%s addr=%s key_idx=%d", - __func__, alg, ether_sprintf(addr), key_idx); - - if (strcmp(alg, "WEP") == 0) - cipher = IEEE80211_CIPHER_WEP; - else if (strcmp(alg, "TKIP") == 0) - cipher = IEEE80211_CIPHER_TKIP; - else if (strcmp(alg, "CCMP") == 0) - cipher = IEEE80211_CIPHER_AES_CCM; - else { - printf("%s: unknown/unsupported algorithm %s\n", - __func__, alg); - return -1; - } - - if (key_len > sizeof(wk.ik_keydata)) { - printf("%s: key length %d too big\n", __func__, key_len); - return -3; - } - - memset(&wk, 0, sizeof(wk)); - wk.ik_type = cipher; - wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT; - if (addr == NULL) { - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - wk.ik_keyix = key_idx; - wk.ik_flags |= IEEE80211_KEY_DEFAULT; - } else { - memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - wk.ik_keyix = IEEE80211_KEYIX_NONE; - } - wk.ik_keylen = key_len; - memcpy(wk.ik_keydata, key, key_len); - - return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); -} - - -static int -bsd_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, - u8 *seq) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_key wk; - - wpa_printf(MSG_DEBUG, "%s: addr=%s idx=%d", - __func__, ether_sprintf(addr), idx); - - memset(&wk, 0, sizeof(wk)); - if (addr == NULL) - memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); - else - memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); - wk.ik_keyix = idx; - - if (get80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)) < 0) { - printf("Failed to get encryption.\n"); - return -1; - } - -#ifdef WORDS_BIGENDIAN - { - /* - * wk.ik_keytsc is in host byte order (big endian), need to - * swap it to match with the byte order used in WPA. - */ - int i; - u8 tmp[WPA_KEY_RSC_LEN]; - memcpy(tmp, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); - for (i = 0; i < WPA_KEY_RSC_LEN; i++) { - seq[i] = tmp[WPA_KEY_RSC_LEN - i - 1]; - } - } -#else /* WORDS_BIGENDIAN */ - memcpy(seq, &wk.ik_keytsc, sizeof(wk.ik_keytsc)); -#endif /* WORDS_BIGENDIAN */ - return 0; -} - - -static int -bsd_flush(void *priv) -{ - u8 allsta[IEEE80211_ADDR_LEN]; - - memset(allsta, 0xff, IEEE80211_ADDR_LEN); - return bsd_sta_deauth(priv, allsta, IEEE80211_REASON_AUTH_LEAVE); -} - - -static int -bsd_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, - const u8 *addr) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_sta_stats stats; - - memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); - if (get80211var(drv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)) > 0) { - /* XXX? do packets counts include non-data frames? */ - data->rx_packets = stats.is_stats.ns_rx_data; - data->rx_bytes = stats.is_stats.ns_rx_bytes; - data->tx_packets = stats.is_stats.ns_tx_data; - data->tx_bytes = stats.is_stats.ns_tx_bytes; - } - return 0; -} - -static int -bsd_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len) -{ - /* - * Do nothing; we setup parameters at startup that define the - * contents of the beacon information element. - */ - return 0; -} - -static int -bsd_sta_deauth(void *priv, const u8 *addr, int reason_code) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - - wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", - __func__, ether_sprintf(addr), reason_code); - - mlme.im_op = IEEE80211_MLME_DEAUTH; - mlme.im_reason = reason_code; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); -} - -static int -bsd_sta_disassoc(void *priv, const u8 *addr, int reason_code) -{ - struct bsd_driver_data *drv = priv; - struct ieee80211req_mlme mlme; - - wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", - __func__, ether_sprintf(addr), reason_code); - - mlme.im_op = IEEE80211_MLME_DISASSOC; - mlme.im_reason = reason_code; - memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); - return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); -} - -static int -bsd_del_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) -{ - struct hostapd_data *hapd = drv->hapd; - struct hostapd_bss_config *conf = hapd->conf; - struct sta_info *sta; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "deassociated"); - - sta = ap_get_sta(hapd, addr); - if (sta != NULL) { - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - if (conf->wpa) - wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); - sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; - ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - ap_free_sta(hapd, sta); - } - return 0; -} - -static int -bsd_new_sta(struct bsd_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) -{ - struct hostapd_data *hapd = drv->hapd; - struct hostapd_bss_config *conf = hapd->conf; - struct sta_info *sta; - struct ieee80211req_wpaie ie; - int new_assoc, ielen, res; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "associated"); - - sta = ap_sta_add(hapd, addr); - if (sta == NULL) - return -1; - /* - * Fetch and validate any negotiated WPA/RSN parameters. - */ - if (conf->wpa) { - memset(&ie, 0, sizeof(ie)); - memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN); - if (get80211var(drv, IEEE80211_IOC_WPAIE, &ie, sizeof(ie)) < 0) { - printf("Failed to get WPA/RSN information element.\n"); - return -1; /* XXX not right */ - } - ielen = ie.wpa_ie[1]; - if (ielen == 0) { - printf("No WPA/RSN information element for station!\n"); - return -1; /* XXX not right */ - } - ielen += 2; - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, - sta->addr); - if (sta->wpa_sm == NULL) { - printf("Failed to initialize WPA state machine\n"); - return -1; - } - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, - ie.wpa_ie, ielen, NULL, 0); - if (res != WPA_IE_OK) { - printf("WPA/RSN information element rejected? " - "(res %u)\n", res); - return -1; - } - } - - /* - * Now that the internal station state is setup - * kick the authenticator into action. - */ - new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; - sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; - wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); - hostapd_new_assoc_sta(hapd, sta, !new_assoc); - ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); - return 0; -} - -#include -#include - -static void -bsd_wireless_event_receive(int sock, void *ctx, void *sock_ctx) -{ - struct bsd_driver_data *drv = ctx; - struct hostapd_data *hapd = drv->hapd; - char buf[2048]; - struct if_announcemsghdr *ifan; - struct rt_msghdr *rtm; - struct ieee80211_michael_event *mic; - struct ieee80211_join_event *join; - struct ieee80211_leave_event *leave; - int n; - - n = read(sock, buf, sizeof(buf)); - if (n < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("read(PF_ROUTE)"); - return; - } - - rtm = (struct rt_msghdr *) buf; - if (rtm->rtm_version != RTM_VERSION) { - wpa_printf(MSG_DEBUG, "Routing message version %d not " - "understood\n", rtm->rtm_version); - return; - } - ifan = (struct if_announcemsghdr *) rtm; - switch (rtm->rtm_type) { - case RTM_IEEE80211: - switch (ifan->ifan_what) { - case RTM_IEEE80211_ASSOC: - case RTM_IEEE80211_REASSOC: - case RTM_IEEE80211_DISASSOC: - case RTM_IEEE80211_SCAN: - break; - case RTM_IEEE80211_LEAVE: - leave = (struct ieee80211_leave_event *) &ifan[1]; - bsd_del_sta(drv, leave->iev_addr); - break; - case RTM_IEEE80211_JOIN: -#ifdef RTM_IEEE80211_REJOIN - case RTM_IEEE80211_REJOIN: -#endif - join = (struct ieee80211_join_event *) &ifan[1]; - bsd_new_sta(drv, join->iev_addr); - break; - case RTM_IEEE80211_REPLAY: - /* ignore */ - break; - case RTM_IEEE80211_MICHAEL: - mic = (struct ieee80211_michael_event *) &ifan[1]; - wpa_printf(MSG_DEBUG, - "Michael MIC failure wireless event: " - "keyix=%u src_addr=" MACSTR, mic->iev_keyix, - MAC2STR(mic->iev_src)); - ieee80211_michael_mic_failure(hapd, mic->iev_src, 1); - break; - } - break; - } -} - -static int -bsd_wireless_event_init(void *priv) -{ - struct bsd_driver_data *drv = priv; - int s; - - drv->wext_sock = -1; - - s = socket(PF_ROUTE, SOCK_RAW, 0); - if (s < 0) { - perror("socket(PF_ROUTE,SOCK_RAW)"); - return -1; - } - eloop_register_read_sock(s, bsd_wireless_event_receive, drv, NULL); - drv->wext_sock = s; - - return 0; -} - -static void -bsd_wireless_event_deinit(void *priv) -{ - struct bsd_driver_data *drv = priv; - - if (drv != NULL) { - if (drv->wext_sock < 0) - return; - eloop_unregister_read_sock(drv->wext_sock); - close(drv->wext_sock); - } -} - - -static int -bsd_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, - int encrypt, const u8 *own_addr) -{ - struct bsd_driver_data *drv = priv; - unsigned char buf[3000]; - unsigned char *bp = buf; - struct l2_ethhdr *eth; - size_t len; - int status; - - /* - * Prepend the Etherent header. If the caller left us - * space at the front we could just insert it but since - * we don't know we copy to a local buffer. Given the frequency - * and size of frames this probably doesn't matter. - */ - len = data_len + sizeof(struct l2_ethhdr); - if (len > sizeof(buf)) { - bp = malloc(len); - if (bp == NULL) { - printf("EAPOL frame discarded, cannot malloc temp " - "buffer of size %u!\n", len); - return -1; - } - } - eth = (struct l2_ethhdr *) bp; - memcpy(eth->h_dest, addr, ETH_ALEN); - memcpy(eth->h_source, own_addr, ETH_ALEN); - eth->h_proto = htons(ETH_P_EAPOL); - memcpy(eth+1, data, data_len); - - wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len); - - status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, bp, len); - - if (bp != buf) - free(bp); - return status; -} - -static void -handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) -{ - struct bsd_driver_data *drv = ctx; - struct hostapd_data *hapd = drv->hapd; - struct sta_info *sta; - - sta = ap_get_sta(hapd, src_addr); - if (!sta || !(sta->flags & WLAN_STA_ASSOC)) { - printf("Data frame from not associated STA %s\n", - ether_sprintf(src_addr)); - /* XXX cannot happen */ - return; - } - ieee802_1x_receive(hapd, src_addr, buf + sizeof(struct l2_ethhdr), - len - sizeof(struct l2_ethhdr)); -} - -static int -bsd_get_ssid(const char *ifname, void *priv, u8 *buf, int len) -{ - struct bsd_driver_data *drv = priv; - int ssid_len = get80211var(drv, IEEE80211_IOC_SSID, buf, len); - - wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, ssid_len, buf); - - return ssid_len; -} - -static int -bsd_set_ssid(const char *ifname, void *priv, const u8 *buf, int len) -{ - struct bsd_driver_data *drv = priv; - - wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, len, buf); - - return set80211var(drv, IEEE80211_IOC_SSID, buf, len); -} - -static void * -bsd_init(struct hostapd_data *hapd) -{ - struct bsd_driver_data *drv; - - drv = os_zalloc(sizeof(struct bsd_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for bsd driver data\n"); - goto bad; - } - - drv->hapd = hapd; - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - goto bad; - } - memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface)); - - drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL, - handle_read, drv, 1); - if (drv->sock_xmit == NULL) - goto bad; - if (l2_packet_get_own_addr(drv->sock_xmit, hapd->own_addr)) - goto bad; - - bsd_set_iface_flags(drv, 0); /* mark down during setup */ - - return drv; -bad: - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv != NULL) - free(drv); - return NULL; -} - - -static void -bsd_deinit(void *priv) -{ - struct bsd_driver_data *drv = priv; - - (void) bsd_set_iface_flags(drv, 0); - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - if (drv->sock_xmit != NULL) - l2_packet_deinit(drv->sock_xmit); - free(drv); -} - -const struct wpa_driver_ops wpa_driver_bsd_ops = { - .name = "bsd", - .init = bsd_init, - .deinit = bsd_deinit, - .set_ieee8021x = bsd_set_ieee8021x, - .set_privacy = bsd_set_privacy, - .set_encryption = bsd_set_key, - .get_seqnum = bsd_get_seqnum, - .flush = bsd_flush, - .set_generic_elem = bsd_set_opt_ie, - .wireless_event_init = bsd_wireless_event_init, - .wireless_event_deinit = bsd_wireless_event_deinit, - .sta_set_flags = bsd_sta_set_flags, - .read_sta_data = bsd_read_sta_driver_data, - .send_eapol = bsd_send_eapol, - .sta_disassoc = bsd_sta_disassoc, - .sta_deauth = bsd_sta_deauth, - .set_ssid = bsd_set_ssid, - .get_ssid = bsd_get_ssid, -}; diff --git a/contrib/wpa/hostapd/driver_hostap.c b/contrib/wpa/hostapd/driver_hostap.c deleted file mode 100644 index ceff0998919c..000000000000 --- a/contrib/wpa/hostapd/driver_hostap.c +++ /dev/null @@ -1,1279 +0,0 @@ -/* - * hostapd / Kernel driver communication with Linux Host AP driver - * Copyright (c) 2002-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#ifdef USE_KERNEL_HEADERS -/* compat-wireless does not include linux/compiler.h to define __user, so - * define it here */ -#ifndef __user -#define __user -#endif /* __user */ -#include -#include -#include /* The L2 protocols */ -#include -#include -#else /* USE_KERNEL_HEADERS */ -#include -#include -#include "wireless_copy.h" -#endif /* USE_KERNEL_HEADERS */ - -#include "hostapd.h" -#include "driver.h" -#include "ieee802_1x.h" -#include "eloop.h" -#include "priv_netlink.h" -#include "ieee802_11.h" -#include "sta_info.h" -#include "hostap_common.h" -#include "hw_features.h" - - -struct hostap_driver_data { - struct hostapd_data *hapd; - - char iface[IFNAMSIZ + 1]; - int sock; /* raw packet socket for driver access */ - int ioctl_sock; /* socket for ioctl() use */ - int wext_sock; /* socket for wireless events */ - - int we_version; - - u8 *generic_ie; - size_t generic_ie_len; - u8 *wps_ie; - size_t wps_ie_len; -}; - - -static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param, - int len); -static int hostap_set_iface_flags(void *priv, int dev_up); - -static void handle_data(struct hostapd_data *hapd, u8 *buf, size_t len, - u16 stype) -{ - struct ieee80211_hdr *hdr; - u16 fc, ethertype; - u8 *pos, *sa; - size_t left; - struct sta_info *sta; - - if (len < sizeof(struct ieee80211_hdr)) - return; - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - - if ((fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) != WLAN_FC_TODS) { - printf("Not ToDS data frame (fc=0x%04x)\n", fc); - return; - } - - sa = hdr->addr2; - sta = ap_get_sta(hapd, sa); - if (!sta || !(sta->flags & WLAN_STA_ASSOC)) { - printf("Data frame from not associated STA " MACSTR "\n", - MAC2STR(sa)); - if (sta && (sta->flags & WLAN_STA_AUTH)) - hostapd_sta_disassoc( - hapd, sa, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - else - hostapd_sta_deauth( - hapd, sa, - WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - return; - } - - pos = (u8 *) (hdr + 1); - left = len - sizeof(*hdr); - - if (left < sizeof(rfc1042_header)) { - printf("Too short data frame\n"); - return; - } - - if (memcmp(pos, rfc1042_header, sizeof(rfc1042_header)) != 0) { - printf("Data frame with no RFC1042 header\n"); - return; - } - pos += sizeof(rfc1042_header); - left -= sizeof(rfc1042_header); - - if (left < 2) { - printf("No ethertype in data frame\n"); - return; - } - - ethertype = WPA_GET_BE16(pos); - pos += 2; - left -= 2; - switch (ethertype) { - case ETH_P_PAE: - ieee802_1x_receive(hapd, sa, pos, left); - break; - - default: - printf("Unknown ethertype 0x%04x in data frame\n", ethertype); - break; - } -} - - -static void handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len, - int ok) -{ - struct ieee80211_hdr *hdr; - u16 fc, type, stype; - struct sta_info *sta; - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - - switch (type) { - case WLAN_FC_TYPE_MGMT: - wpa_printf(MSG_DEBUG, "MGMT (TX callback) %s", - ok ? "ACK" : "fail"); - ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); - break; - case WLAN_FC_TYPE_CTRL: - wpa_printf(MSG_DEBUG, "CTRL (TX callback) %s", - ok ? "ACK" : "fail"); - break; - case WLAN_FC_TYPE_DATA: - wpa_printf(MSG_DEBUG, "DATA (TX callback) %s", - ok ? "ACK" : "fail"); - sta = ap_get_sta(hapd, hdr->addr1); - if (sta && sta->flags & WLAN_STA_PENDING_POLL) { - wpa_printf(MSG_DEBUG, "STA " MACSTR - " %s pending activity poll", - MAC2STR(sta->addr), - ok ? "ACKed" : "did not ACK"); - if (ok) - sta->flags &= ~WLAN_STA_PENDING_POLL; - } - if (sta) - ieee802_1x_tx_status(hapd, sta, buf, len, ok); - break; - default: - printf("unknown TX callback frame type %d\n", type); - break; - } -} - - -static void handle_frame(struct hostapd_data *hapd, u8 *buf, size_t len) -{ - struct ieee80211_hdr *hdr; - u16 fc, extra_len, type, stype; - unsigned char *extra = NULL; - size_t data_len = len; - int ver; - - /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass - * these to user space */ - if (len < 24) { - wpa_printf(MSG_MSGDUMP, "handle_frame: too short (%lu)", - (unsigned long) len); - return; - } - - hdr = (struct ieee80211_hdr *) buf; - fc = le_to_host16(hdr->frame_control); - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - - if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON) { - wpa_hexdump(MSG_MSGDUMP, "Received management frame", - buf, len); - } - - ver = fc & WLAN_FC_PVER; - - /* protocol version 3 is reserved for indicating extra data after the - * payload, version 2 for indicating ACKed frame (TX callbacks), and - * version 1 for indicating failed frame (no ACK, TX callbacks) */ - if (ver == 3) { - u8 *pos = buf + len - 2; - extra_len = WPA_GET_LE16(pos); - printf("extra data in frame (elen=%d)\n", extra_len); - if ((size_t) extra_len + 2 > len) { - printf(" extra data overflow\n"); - return; - } - len -= extra_len + 2; - extra = buf + len; - } else if (ver == 1 || ver == 2) { - handle_tx_callback(hapd, buf, data_len, ver == 2 ? 1 : 0); - return; - } else if (ver != 0) { - printf("unknown protocol version %d\n", ver); - return; - } - - switch (type) { - case WLAN_FC_TYPE_MGMT: - if (stype != WLAN_FC_STYPE_BEACON) - wpa_printf(MSG_MSGDUMP, "MGMT"); - ieee802_11_mgmt(hapd, buf, data_len, stype, NULL); - break; - case WLAN_FC_TYPE_CTRL: - wpa_printf(MSG_DEBUG, "CTRL"); - break; - case WLAN_FC_TYPE_DATA: - wpa_printf(MSG_DEBUG, "DATA"); - handle_data(hapd, buf, data_len, stype); - break; - default: - wpa_printf(MSG_DEBUG, "unknown frame type %d", type); - break; - } -} - - -static void handle_read(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx; - int len; - unsigned char buf[3000]; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv"); - return; - } - - handle_frame(hapd, buf, len); -} - - -static int hostap_init_sockets(struct hostap_driver_data *drv) -{ - struct ifreq ifr; - struct sockaddr_ll addr; - - drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); - if (drv->sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - return -1; - } - - if (eloop_register_read_sock(drv->sock, handle_read, drv->hapd, NULL)) - { - printf("Could not register read socket\n"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface); - if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - return -1; - } - - if (hostap_set_iface_flags(drv, 1)) { - return -1; - } - - memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_ifindex = ifr.ifr_ifindex; - wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", - addr.sll_ifindex); - - if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); - if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) { - perror("ioctl(SIOCGIFHWADDR)"); - return -1; - } - - if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { - printf("Invalid HW-addr family 0x%04x\n", - ifr.ifr_hwaddr.sa_family); - return -1; - } - memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - - return 0; -} - - -static int hostap_send_mgmt_frame(void *priv, const void *msg, size_t len, - int flags) -{ - struct hostap_driver_data *drv = priv; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg; - int res; - - /* Request TX callback */ - hdr->frame_control |= host_to_le16(BIT(1)); - res = send(drv->sock, msg, len, flags); - hdr->frame_control &= ~host_to_le16(BIT(1)); - - return res; -} - - -static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data, - size_t data_len, int encrypt, const u8 *own_addr) -{ - struct hostap_driver_data *drv = priv; - struct ieee80211_hdr *hdr; - size_t len; - u8 *pos; - int res; - - len = sizeof(*hdr) + sizeof(rfc1042_header) + 2 + data_len; - hdr = os_zalloc(len); - if (hdr == NULL) { - printf("malloc() failed for hostapd_send_data(len=%lu)\n", - (unsigned long) len); - return -1; - } - - hdr->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); - hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS); - if (encrypt) - hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP); - memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN); - memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); - memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); - - pos = (u8 *) (hdr + 1); - memcpy(pos, rfc1042_header, sizeof(rfc1042_header)); - pos += sizeof(rfc1042_header); - *((u16 *) pos) = htons(ETH_P_PAE); - pos += 2; - memcpy(pos, data, data_len); - - res = hostap_send_mgmt_frame(drv, (u8 *) hdr, len, 0); - free(hdr); - - if (res < 0) { - perror("hostapd_send_eapol: send"); - printf("hostapd_send_eapol - packet len: %lu - failed\n", - (unsigned long) len); - } - - return res; -} - - -static int hostap_sta_set_flags(void *priv, const u8 *addr, - int total_flags, int flags_or, int flags_and) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA; - memcpy(param.sta_addr, addr, ETH_ALEN); - param.u.set_flags_sta.flags_or = flags_or; - param.u.set_flags_sta.flags_and = flags_and; - return hostapd_ioctl(drv, ¶m, sizeof(param)); -} - - -static int hostap_set_iface_flags(void *priv, int dev_up) -{ - struct hostap_driver_data *drv = priv; - struct ifreq ifr; - - if (drv->ioctl_sock < 0) - return -1; - - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, IFNAMSIZ, "%sap", drv->iface); - - if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCGIFFLAGS]"); - return -1; - } - - if (dev_up) - ifr.ifr_flags |= IFF_UP; - else - ifr.ifr_flags &= ~IFF_UP; - - if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); - return -1; - } - - if (dev_up) { - memset(&ifr, 0, sizeof(ifr)); - snprintf(ifr.ifr_name, IFNAMSIZ, "%sap", drv->iface); - ifr.ifr_mtu = HOSTAPD_MTU; - if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) { - perror("ioctl[SIOCSIFMTU]"); - printf("Setting MTU failed - trying to survive with " - "current value\n"); - } - } - - return 0; -} - - -static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param, - int len) -{ - struct hostap_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) param; - iwr.u.data.length = len; - - if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) { - perror("ioctl[PRISM2_IOCTL_HOSTAPD]"); - return -1; - } - - return 0; -} - - -static int hostap_set_encryption(const char *ifname, void *priv, - const char *alg, const u8 *addr, - int idx, const u8 *key, size_t key_len, - int txkey) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param *param; - u8 *buf; - size_t blen; - int ret = 0; - - blen = sizeof(*param) + key_len; - buf = os_zalloc(blen); - if (buf == NULL) - return -1; - - param = (struct prism2_hostapd_param *) buf; - param->cmd = PRISM2_SET_ENCRYPTION; - if (addr == NULL) - memset(param->sta_addr, 0xff, ETH_ALEN); - else - memcpy(param->sta_addr, addr, ETH_ALEN); - os_strlcpy((char *) param->u.crypt.alg, alg, - HOSTAP_CRYPT_ALG_NAME_LEN); - param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; - param->u.crypt.idx = idx; - param->u.crypt.key_len = key_len; - memcpy((u8 *) (param + 1), key, key_len); - - if (hostapd_ioctl(drv, param, blen)) { - printf("Failed to set encryption.\n"); - ret = -1; - } - free(buf); - - return ret; -} - - -static int hostap_get_seqnum(const char *ifname, void *priv, const u8 *addr, - int idx, u8 *seq) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param *param; - u8 *buf; - size_t blen; - int ret = 0; - - blen = sizeof(*param) + 32; - buf = os_zalloc(blen); - if (buf == NULL) - return -1; - - param = (struct prism2_hostapd_param *) buf; - param->cmd = PRISM2_GET_ENCRYPTION; - if (addr == NULL) - memset(param->sta_addr, 0xff, ETH_ALEN); - else - memcpy(param->sta_addr, addr, ETH_ALEN); - param->u.crypt.idx = idx; - - if (hostapd_ioctl(drv, param, blen)) { - printf("Failed to get encryption.\n"); - ret = -1; - } else { - memcpy(seq, param->u.crypt.seq, 8); - } - free(buf); - - return ret; -} - - -static int hostap_ioctl_prism2param(void *priv, int param, int value) -{ - struct hostap_driver_data *drv = priv; - struct iwreq iwr; - int *i; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - i = (int *) iwr.u.name; - *i++ = param; - *i++ = value; - - if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) { - perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]"); - return -1; - } - - return 0; -} - - -static int hostap_set_ieee8021x(const char *ifname, void *priv, int enabled) -{ - struct hostap_driver_data *drv = priv; - - /* enable kernel driver support for IEEE 802.1X */ - if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_IEEE_802_1X, enabled)) { - printf("Could not setup IEEE 802.1X support in kernel driver." - "\n"); - return -1; - } - - if (!enabled) - return 0; - - /* use host driver implementation of encryption to allow - * individual keys and passing plaintext EAPOL frames */ - if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_DECRYPT, 1) || - hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_ENCRYPT, 1)) { - printf("Could not setup host-based encryption in kernel " - "driver.\n"); - return -1; - } - - return 0; -} - - -static int hostap_set_privacy(const char *ifname, void *priv, int enabled) -{ - struct hostap_drvier_data *drv = priv; - - return hostap_ioctl_prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED, - enabled); -} - - -static int hostap_set_ssid(const char *ifname, void *priv, const u8 *buf, - int len) -{ - struct hostap_driver_data *drv = priv; - struct iwreq iwr; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.essid.flags = 1; /* SSID active */ - iwr.u.essid.pointer = (caddr_t) buf; - iwr.u.essid.length = len + 1; - - if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { - perror("ioctl[SIOCSIWESSID]"); - printf("len=%d\n", len); - return -1; - } - - return 0; -} - - -static int hostap_flush(void *priv) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_FLUSH; - return hostapd_ioctl(drv, ¶m, sizeof(param)); -} - - -static int hostap_read_sta_data(void *priv, - struct hostap_sta_driver_data *data, - const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - char buf[1024], line[128], *pos; - FILE *f; - unsigned long val; - - memset(data, 0, sizeof(*data)); - snprintf(buf, sizeof(buf), "/proc/net/hostap/%s/" MACSTR, - drv->iface, MAC2STR(addr)); - - f = fopen(buf, "r"); - if (!f) - return -1; - /* Need to read proc file with in one piece, so use large enough - * buffer. */ - setbuffer(f, buf, sizeof(buf)); - - while (fgets(line, sizeof(line), f)) { - pos = strchr(line, '='); - if (!pos) - continue; - *pos++ = '\0'; - val = strtoul(pos, NULL, 10); - if (strcmp(line, "rx_packets") == 0) - data->rx_packets = val; - else if (strcmp(line, "tx_packets") == 0) - data->tx_packets = val; - else if (strcmp(line, "rx_bytes") == 0) - data->rx_bytes = val; - else if (strcmp(line, "tx_bytes") == 0) - data->tx_bytes = val; - } - - fclose(f); - - return 0; -} - - -static int hostap_sta_add(const char *ifname, void *priv, const u8 *addr, - u16 aid, u16 capability, u8 *supp_rates, - size_t supp_rates_len, int flags, - u16 listen_interval) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - int tx_supp_rates = 0; - size_t i; - -#define WLAN_RATE_1M BIT(0) -#define WLAN_RATE_2M BIT(1) -#define WLAN_RATE_5M5 BIT(2) -#define WLAN_RATE_11M BIT(3) - - for (i = 0; i < supp_rates_len; i++) { - if ((supp_rates[i] & 0x7f) == 2) - tx_supp_rates |= WLAN_RATE_1M; - if ((supp_rates[i] & 0x7f) == 4) - tx_supp_rates |= WLAN_RATE_2M; - if ((supp_rates[i] & 0x7f) == 11) - tx_supp_rates |= WLAN_RATE_5M5; - if ((supp_rates[i] & 0x7f) == 22) - tx_supp_rates |= WLAN_RATE_11M; - } - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_ADD_STA; - memcpy(param.sta_addr, addr, ETH_ALEN); - param.u.add_sta.aid = aid; - param.u.add_sta.capability = capability; - param.u.add_sta.tx_supp_rates = tx_supp_rates; - return hostapd_ioctl(drv, ¶m, sizeof(param)); -} - - -static int hostap_sta_remove(void *priv, const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - hostap_sta_set_flags(drv, addr, 0, 0, ~WLAN_STA_AUTHORIZED); - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_REMOVE_STA; - memcpy(param.sta_addr, addr, ETH_ALEN); - if (hostapd_ioctl(drv, ¶m, sizeof(param))) { - printf("Could not remove station from kernel driver.\n"); - return -1; - } - return 0; -} - - -static int hostap_get_inact_sec(void *priv, const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_GET_INFO_STA; - memcpy(param.sta_addr, addr, ETH_ALEN); - if (hostapd_ioctl(drv, ¶m, sizeof(param))) { - return -1; - } - - return param.u.get_info_sta.inactive_sec; -} - - -static int hostap_sta_clear_stats(void *priv, const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_STA_CLEAR_STATS; - memcpy(param.sta_addr, addr, ETH_ALEN); - if (hostapd_ioctl(drv, ¶m, sizeof(param))) { - return -1; - } - - return 0; -} - - -static int hostap_set_assoc_ap(void *priv, const u8 *addr) -{ - struct hostap_driver_data *drv = priv; - struct prism2_hostapd_param param; - - memset(¶m, 0, sizeof(param)); - param.cmd = PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR; - memcpy(param.sta_addr, addr, ETH_ALEN); - if (hostapd_ioctl(drv, ¶m, sizeof(param))) - return -1; - - return 0; -} - - -static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv) -{ - struct prism2_hostapd_param *param; - int res; - size_t blen, elem_len; - - elem_len = drv->generic_ie_len + drv->wps_ie_len; - blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + elem_len; - if (blen < sizeof(*param)) - blen = sizeof(*param); - - param = os_zalloc(blen); - if (param == NULL) - return -1; - - param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT; - param->u.generic_elem.len = elem_len; - if (drv->generic_ie) { - os_memcpy(param->u.generic_elem.data, drv->generic_ie, - drv->generic_ie_len); - } - if (drv->wps_ie) { - os_memcpy(¶m->u.generic_elem.data[drv->generic_ie_len], - drv->wps_ie, drv->wps_ie_len); - } - wpa_hexdump(MSG_DEBUG, "hostap: Set generic IE", - param->u.generic_elem.data, elem_len); - res = hostapd_ioctl(drv, param, blen); - - os_free(param); - - return res; -} - - -static int hostap_set_generic_elem(const char *ifname, void *priv, - const u8 *elem, size_t elem_len) -{ - struct hostap_driver_data *drv = priv; - - os_free(drv->generic_ie); - drv->generic_ie = NULL; - drv->generic_ie_len = 0; - if (elem) { - drv->generic_ie = os_malloc(elem_len); - if (drv->generic_ie == NULL) - return -1; - os_memcpy(drv->generic_ie, elem, elem_len); - drv->generic_ie_len = elem_len; - } - - return hostapd_ioctl_set_generic_elem(drv); -} - - -static int hostap_set_wps_beacon_ie(const char *ifname, void *priv, - const u8 *ie, size_t len) -{ - /* Host AP driver supports only one set of extra IEs, so we need to - * use the ProbeResp IEs also for Beacon frames since they include more - * information. */ - return 0; -} - - -static int hostap_set_wps_probe_resp_ie(const char *ifname, void *priv, - const u8 *ie, size_t len) -{ - struct hostap_driver_data *drv = priv; - - os_free(drv->wps_ie); - drv->wps_ie = NULL; - drv->wps_ie_len = 0; - if (ie) { - drv->wps_ie = os_malloc(len); - if (drv->wps_ie == NULL) - return -1; - os_memcpy(drv->wps_ie, ie, len); - drv->wps_ie_len = len; - } - - return hostapd_ioctl_set_generic_elem(drv); -} - - -static void -hostapd_wireless_event_wireless_custom(struct hostap_driver_data *drv, - char *custom) -{ - wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom); - - if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) { - char *pos; - u8 addr[ETH_ALEN]; - pos = strstr(custom, "addr="); - if (pos == NULL) { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "without sender address ignored"); - return; - } - pos += 5; - if (hwaddr_aton(pos, addr) == 0) { - ieee80211_michael_mic_failure(drv->hapd, addr, 1); - } else { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "with invalid MAC address"); - } - } -} - - -static void hostapd_wireless_event_wireless(struct hostap_driver_data *drv, - char *data, int len) -{ - struct iw_event iwe_buf, *iwe = &iwe_buf; - char *pos, *end, *custom, *buf; - - pos = data; - end = data + len; - - while (pos + IW_EV_LCP_LEN <= end) { - /* Event data may be unaligned, so make a local, aligned copy - * before processing. */ - memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); - wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", - iwe->cmd, iwe->len); - if (iwe->len <= IW_EV_LCP_LEN) - return; - - custom = pos + IW_EV_POINT_LEN; - if (drv->we_version > 18 && - (iwe->cmd == IWEVMICHAELMICFAILURE || - iwe->cmd == IWEVCUSTOM)) { - /* WE-19 removed the pointer from struct iw_point */ - char *dpos = (char *) &iwe_buf.u.data.length; - int dlen = dpos - (char *) &iwe_buf; - memcpy(dpos, pos + IW_EV_LCP_LEN, - sizeof(struct iw_event) - dlen); - } else { - memcpy(&iwe_buf, pos, sizeof(struct iw_event)); - custom += IW_EV_POINT_OFF; - } - - switch (iwe->cmd) { - case IWEVCUSTOM: - if (custom + iwe->u.data.length > end) - return; - buf = malloc(iwe->u.data.length + 1); - if (buf == NULL) - return; - memcpy(buf, custom, iwe->u.data.length); - buf[iwe->u.data.length] = '\0'; - hostapd_wireless_event_wireless_custom(drv, buf); - free(buf); - break; - } - - pos += iwe->len; - } -} - - -static void hostapd_wireless_event_rtm_newlink(struct hostap_driver_data *drv, - struct nlmsghdr *h, int len) -{ - struct ifinfomsg *ifi; - int attrlen, nlmsg_len, rta_len; - struct rtattr * attr; - - if (len < (int) sizeof(*ifi)) - return; - - ifi = NLMSG_DATA(h); - - /* TODO: use ifi->ifi_index to filter out wireless events from other - * interfaces */ - - nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); - - attrlen = h->nlmsg_len - nlmsg_len; - if (attrlen < 0) - return; - - attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); - - rta_len = RTA_ALIGN(sizeof(struct rtattr)); - while (RTA_OK(attr, attrlen)) { - if (attr->rta_type == IFLA_WIRELESS) { - hostapd_wireless_event_wireless( - drv, ((char *) attr) + rta_len, - attr->rta_len - rta_len); - } - attr = RTA_NEXT(attr, attrlen); - } -} - - -static void hostapd_wireless_event_receive(int sock, void *eloop_ctx, - void *sock_ctx) -{ - char buf[256]; - int left; - struct sockaddr_nl from; - socklen_t fromlen; - struct nlmsghdr *h; - struct hostap_driver_data *drv = eloop_ctx; - - fromlen = sizeof(from); - left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); - if (left < 0) { - if (errno != EINTR && errno != EAGAIN) - perror("recvfrom(netlink)"); - return; - } - - h = (struct nlmsghdr *) buf; - while (left >= (int) sizeof(*h)) { - int len, plen; - - len = h->nlmsg_len; - plen = len - sizeof(*h); - if (len > left || plen < 0) { - printf("Malformed netlink message: " - "len=%d left=%d plen=%d\n", - len, left, plen); - break; - } - - switch (h->nlmsg_type) { - case RTM_NEWLINK: - hostapd_wireless_event_rtm_newlink(drv, h, plen); - break; - } - - len = NLMSG_ALIGN(len); - left -= len; - h = (struct nlmsghdr *) ((char *) h + len); - } - - if (left > 0) { - printf("%d extra bytes in the end of netlink message\n", left); - } -} - - -static int hostap_get_we_version(struct hostap_driver_data *drv) -{ - struct iw_range *range; - struct iwreq iwr; - int minlen; - size_t buflen; - - drv->we_version = 0; - - /* - * Use larger buffer than struct iw_range in order to allow the - * structure to grow in the future. - */ - buflen = sizeof(struct iw_range) + 500; - range = os_zalloc(buflen); - if (range == NULL) - return -1; - - memset(&iwr, 0, sizeof(iwr)); - os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); - iwr.u.data.pointer = (caddr_t) range; - iwr.u.data.length = buflen; - - minlen = ((char *) &range->enc_capa) - (char *) range + - sizeof(range->enc_capa); - - if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { - perror("ioctl[SIOCGIWRANGE]"); - free(range); - return -1; - } else if (iwr.u.data.length >= minlen && - range->we_version_compiled >= 18) { - wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " - "WE(source)=%d enc_capa=0x%x", - range->we_version_compiled, - range->we_version_source, - range->enc_capa); - drv->we_version = range->we_version_compiled; - } - - free(range); - return 0; -} - - -static int hostap_wireless_event_init(void *priv) -{ - struct hostap_driver_data *drv = priv; - int s; - struct sockaddr_nl local; - - hostap_get_we_version(drv); - - drv->wext_sock = -1; - - s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (s < 0) { - perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); - return -1; - } - - memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; - local.nl_groups = RTMGRP_LINK; - if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) { - perror("bind(netlink)"); - close(s); - return -1; - } - - eloop_register_read_sock(s, hostapd_wireless_event_receive, drv, - NULL); - drv->wext_sock = s; - - return 0; -} - - -static void hostap_wireless_event_deinit(void *priv) -{ - struct hostap_driver_data *drv = priv; - if (drv->wext_sock < 0) - return; - eloop_unregister_read_sock(drv->wext_sock); - close(drv->wext_sock); -} - - -static void * hostap_init(struct hostapd_data *hapd) -{ - struct hostap_driver_data *drv; - - drv = os_zalloc(sizeof(struct hostap_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for hostapd driver data\n"); - return NULL; - } - - drv->hapd = hapd; - drv->ioctl_sock = drv->sock = -1; - memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface)); - - drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); - if (drv->ioctl_sock < 0) { - perror("socket[PF_INET,SOCK_DGRAM]"); - free(drv); - return NULL; - } - - if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 1)) { - printf("Could not enable hostapd mode for interface %s\n", - drv->iface); - close(drv->ioctl_sock); - free(drv); - return NULL; - } - - if (hostap_init_sockets(drv)) { - close(drv->ioctl_sock); - free(drv); - return NULL; - } - - return drv; -} - - -static void hostap_driver_deinit(void *priv) -{ - struct hostap_driver_data *drv = priv; - - (void) hostap_set_iface_flags(drv, 0); - (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 0); - (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD_STA, 0); - - if (drv->ioctl_sock >= 0) - close(drv->ioctl_sock); - - if (drv->sock >= 0) - close(drv->sock); - - os_free(drv->generic_ie); - os_free(drv->wps_ie); - - free(drv); -} - - -static int hostap_sta_deauth(void *priv, const u8 *addr, int reason) -{ - struct hostap_driver_data *drv = priv; - struct ieee80211_mgmt mgmt; - - memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DEAUTH); - memcpy(mgmt.da, addr, ETH_ALEN); - memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN); - memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN); - mgmt.u.deauth.reason_code = host_to_le16(reason); - return hostap_send_mgmt_frame(drv, &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth), 0); -} - - -static int hostap_sta_disassoc(void *priv, const u8 *addr, int reason) -{ - struct hostap_driver_data *drv = priv; - struct ieee80211_mgmt mgmt; - - memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DISASSOC); - memcpy(mgmt.da, addr, ETH_ALEN); - memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN); - memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN); - mgmt.u.disassoc.reason_code = host_to_le16(reason); - return hostap_send_mgmt_frame(drv, &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.disassoc), 0); -} - - -static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv, - u16 *num_modes, - u16 *flags) -{ - struct hostapd_hw_modes *mode; - int i, clen, rlen; - const short chan2freq[14] = { - 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 - }; - - mode = os_zalloc(sizeof(struct hostapd_hw_modes)); - if (mode == NULL) - return NULL; - - *num_modes = 1; - *flags = 0; - - mode->mode = HOSTAPD_MODE_IEEE80211B; - mode->num_channels = 14; - mode->num_rates = 4; - - clen = mode->num_channels * sizeof(struct hostapd_channel_data); - rlen = mode->num_rates * sizeof(struct hostapd_rate_data); - - mode->channels = os_zalloc(clen); - mode->rates = os_zalloc(rlen); - if (mode->channels == NULL || mode->rates == NULL) { - hostapd_free_hw_features(mode, *num_modes); - return NULL; - } - - for (i = 0; i < 14; i++) { - mode->channels[i].chan = i + 1; - mode->channels[i].freq = chan2freq[i]; - /* TODO: Get allowed channel list from the driver */ - if (i >= 11) - mode->channels[i].flag = HOSTAPD_CHAN_DISABLED; - } - - mode->rates[0].rate = 10; - mode->rates[0].flags = HOSTAPD_RATE_CCK; - mode->rates[1].rate = 20; - mode->rates[1].flags = HOSTAPD_RATE_CCK; - mode->rates[2].rate = 55; - mode->rates[2].flags = HOSTAPD_RATE_CCK; - mode->rates[3].rate = 110; - mode->rates[3].flags = HOSTAPD_RATE_CCK; - - return mode; -} - - -const struct wpa_driver_ops wpa_driver_hostap_ops = { - .name = "hostap", - .init = hostap_init, - .deinit = hostap_driver_deinit, - .wireless_event_init = hostap_wireless_event_init, - .wireless_event_deinit = hostap_wireless_event_deinit, - .set_ieee8021x = hostap_set_ieee8021x, - .set_privacy = hostap_set_privacy, - .set_encryption = hostap_set_encryption, - .get_seqnum = hostap_get_seqnum, - .flush = hostap_flush, - .set_generic_elem = hostap_set_generic_elem, - .read_sta_data = hostap_read_sta_data, - .send_eapol = hostap_send_eapol, - .sta_set_flags = hostap_sta_set_flags, - .sta_deauth = hostap_sta_deauth, - .sta_disassoc = hostap_sta_disassoc, - .sta_remove = hostap_sta_remove, - .set_ssid = hostap_set_ssid, - .send_mgmt_frame = hostap_send_mgmt_frame, - .set_assoc_ap = hostap_set_assoc_ap, - .sta_add = hostap_sta_add, - .get_inact_sec = hostap_get_inact_sec, - .sta_clear_stats = hostap_sta_clear_stats, - .get_hw_feature_data = hostap_get_hw_feature_data, - .set_wps_beacon_ie = hostap_set_wps_beacon_ie, - .set_wps_probe_resp_ie = hostap_set_wps_probe_resp_ie, -}; diff --git a/contrib/wpa/hostapd/driver_wired.c b/contrib/wpa/hostapd/driver_wired.c deleted file mode 100644 index 61cb667cca7f..000000000000 --- a/contrib/wpa/hostapd/driver_wired.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - * hostapd / Kernel driver communication for wired (Ethernet) drivers - * Copyright (c) 2002-2007, Jouni Malinen - * Copyright (c) 2004, Gunter Burchardt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#include - -#ifdef USE_KERNEL_HEADERS -#include -#include -#include /* The L2 protocols */ -#include -#include -#else /* USE_KERNEL_HEADERS */ -#include -#include -#include -#endif /* USE_KERNEL_HEADERS */ - -#include "hostapd.h" -#include "ieee802_1x.h" -#include "eloop.h" -#include "sta_info.h" -#include "driver.h" -#include "accounting.h" - - -struct wired_driver_data { - struct hostapd_data *hapd; - - int sock; /* raw packet socket for driver access */ - int dhcp_sock; /* socket for dhcp packets */ - int use_pae_group_addr; -}; - - -#define WIRED_EAPOL_MULTICAST_GROUP {0x01,0x80,0xc2,0x00,0x00,0x03} - - -/* TODO: detecting new devices should eventually be changed from using DHCP - * snooping to trigger on any packet from a new layer 2 MAC address, e.g., - * based on ebtables, etc. */ - -struct dhcp_message { - u_int8_t op; - u_int8_t htype; - u_int8_t hlen; - u_int8_t hops; - u_int32_t xid; - u_int16_t secs; - u_int16_t flags; - u_int32_t ciaddr; - u_int32_t yiaddr; - u_int32_t siaddr; - u_int32_t giaddr; - u_int8_t chaddr[16]; - u_int8_t sname[64]; - u_int8_t file[128]; - u_int32_t cookie; - u_int8_t options[308]; /* 312 - cookie */ -}; - - -static void wired_possible_new_sta(struct hostapd_data *hapd, u8 *addr) -{ - struct sta_info *sta; - - sta = ap_get_sta(hapd, addr); - if (sta) - return; - - wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR - " - adding a new STA", MAC2STR(addr)); - sta = ap_sta_add(hapd, addr); - if (sta) { - hostapd_new_assoc_sta(hapd, sta, 0); - } else { - wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR, - MAC2STR(addr)); - } -} - - -static void handle_data(struct hostapd_data *hapd, unsigned char *buf, - size_t len) -{ - struct ieee8023_hdr *hdr; - u8 *pos, *sa; - size_t left; - - /* must contain at least ieee8023_hdr 6 byte source, 6 byte dest, - * 2 byte ethertype */ - if (len < 14) { - wpa_printf(MSG_MSGDUMP, "handle_data: too short (%lu)", - (unsigned long) len); - return; - } - - hdr = (struct ieee8023_hdr *) buf; - - switch (ntohs(hdr->ethertype)) { - case ETH_P_PAE: - wpa_printf(MSG_MSGDUMP, "Received EAPOL packet"); - sa = hdr->src; - wired_possible_new_sta(hapd, sa); - - pos = (u8 *) (hdr + 1); - left = len - sizeof(*hdr); - - ieee802_1x_receive(hapd, sa, pos, left); - break; - - default: - wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame", - ntohs(hdr->ethertype)); - break; - } -} - - -static void handle_read(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx; - int len; - unsigned char buf[3000]; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv"); - return; - } - - handle_data(hapd, buf, len); -} - - -static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct hostapd_data *hapd = (struct hostapd_data *) eloop_ctx; - int len; - unsigned char buf[3000]; - struct dhcp_message *msg; - u8 *mac_address; - - len = recv(sock, buf, sizeof(buf), 0); - if (len < 0) { - perror("recv"); - return; - } - - /* must contain at least dhcp_message->chaddr */ - if (len < 44) { - wpa_printf(MSG_MSGDUMP, "handle_dhcp: too short (%d)", len); - return; - } - - msg = (struct dhcp_message *) buf; - mac_address = (u8 *) &(msg->chaddr); - - wpa_printf(MSG_MSGDUMP, "Got DHCP broadcast packet from " MACSTR, - MAC2STR(mac_address)); - - wired_possible_new_sta(hapd, mac_address); -} - - -static int wired_init_sockets(struct wired_driver_data *drv) -{ - struct hostapd_data *hapd = drv->hapd; - struct ifreq ifr; - struct sockaddr_ll addr; - struct sockaddr_in addr2; - struct packet_mreq mreq; - u8 multicastgroup_eapol[6] = WIRED_EAPOL_MULTICAST_GROUP; - int n = 1; - - drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE)); - if (drv->sock < 0) { - perror("socket[PF_PACKET,SOCK_RAW]"); - return -1; - } - - if (eloop_register_read_sock(drv->sock, handle_read, hapd, NULL)) { - printf("Could not register read socket\n"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, hapd->conf->iface, sizeof(ifr.ifr_name)); - if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) { - perror("ioctl(SIOCGIFINDEX)"); - return -1; - } - - - memset(&addr, 0, sizeof(addr)); - addr.sll_family = AF_PACKET; - addr.sll_ifindex = ifr.ifr_ifindex; - wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d", - addr.sll_ifindex); - - if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) { - perror("bind"); - return -1; - } - - /* filter multicast address */ - memset(&mreq, 0, sizeof(mreq)); - mreq.mr_ifindex = ifr.ifr_ifindex; - mreq.mr_type = PACKET_MR_MULTICAST; - mreq.mr_alen = 6; - memcpy(mreq.mr_address, multicastgroup_eapol, mreq.mr_alen); - - if (setsockopt(drv->sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, - sizeof(mreq)) < 0) { - perror("setsockopt[SOL_SOCKET,PACKET_ADD_MEMBERSHIP]"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_name, hapd->conf->iface, sizeof(ifr.ifr_name)); - if (ioctl(drv->sock, SIOCGIFHWADDR, &ifr) != 0) { - perror("ioctl(SIOCGIFHWADDR)"); - return -1; - } - - if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) { - printf("Invalid HW-addr family 0x%04x\n", - ifr.ifr_hwaddr.sa_family); - return -1; - } - memcpy(hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - - /* setup dhcp listen socket for sta detection */ - if ((drv->dhcp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { - perror("socket call failed for dhcp"); - return -1; - } - - if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp, hapd, NULL)) - { - printf("Could not register read socket\n"); - return -1; - } - - memset(&addr2, 0, sizeof(addr2)); - addr2.sin_family = AF_INET; - addr2.sin_port = htons(67); - addr2.sin_addr.s_addr = INADDR_ANY; - - if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n, - sizeof(n)) == -1) { - perror("setsockopt[SOL_SOCKET,SO_REUSEADDR]"); - return -1; - } - if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BROADCAST, (char *) &n, - sizeof(n)) == -1) { - perror("setsockopt[SOL_SOCKET,SO_BROADCAST]"); - return -1; - } - - memset(&ifr, 0, sizeof(ifr)); - os_strlcpy(ifr.ifr_ifrn.ifrn_name, hapd->conf->iface, IFNAMSIZ); - if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE, - (char *) &ifr, sizeof(ifr)) < 0) { - perror("setsockopt[SOL_SOCKET,SO_BINDTODEVICE]"); - return -1; - } - - if (bind(drv->dhcp_sock, (struct sockaddr *) &addr2, - sizeof(struct sockaddr)) == -1) { - perror("bind"); - return -1; - } - - return 0; -} - - -static int wired_send_eapol(void *priv, const u8 *addr, - const u8 *data, size_t data_len, int encrypt, - const u8 *own_addr) -{ - struct wired_driver_data *drv = priv; - u8 pae_group_addr[ETH_ALEN] = WIRED_EAPOL_MULTICAST_GROUP; - struct ieee8023_hdr *hdr; - size_t len; - u8 *pos; - int res; - - len = sizeof(*hdr) + data_len; - hdr = os_zalloc(len); - if (hdr == NULL) { - printf("malloc() failed for wired_send_eapol(len=%lu)\n", - (unsigned long) len); - return -1; - } - - memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr, - ETH_ALEN); - memcpy(hdr->src, own_addr, ETH_ALEN); - hdr->ethertype = htons(ETH_P_PAE); - - pos = (u8 *) (hdr + 1); - memcpy(pos, data, data_len); - - res = send(drv->sock, (u8 *) hdr, len, 0); - free(hdr); - - if (res < 0) { - perror("wired_send_eapol: send"); - printf("wired_send_eapol - packet len: %lu - failed\n", - (unsigned long) len); - } - - return res; -} - - -static void * wired_driver_init(struct hostapd_data *hapd) -{ - struct wired_driver_data *drv; - - drv = os_zalloc(sizeof(struct wired_driver_data)); - if (drv == NULL) { - printf("Could not allocate memory for wired driver data\n"); - return NULL; - } - - drv->hapd = hapd; - drv->use_pae_group_addr = hapd->conf->use_pae_group_addr; - - if (wired_init_sockets(drv)) { - free(drv); - return NULL; - } - - return drv; -} - - -static void wired_driver_deinit(void *priv) -{ - struct wired_driver_data *drv = priv; - - if (drv->sock >= 0) - close(drv->sock); - - if (drv->dhcp_sock >= 0) - close(drv->dhcp_sock); - - free(drv); -} - - -const struct wpa_driver_ops wpa_driver_wired_ops = { - .name = "wired", - .init = wired_driver_init, - .deinit = wired_driver_deinit, - .send_eapol = wired_send_eapol, -}; diff --git a/contrib/wpa/hostapd/drivers.c b/contrib/wpa/hostapd/drivers.c deleted file mode 100644 index bde6e609f3d4..000000000000 --- a/contrib/wpa/hostapd/drivers.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * hostapd / driver interface list - * Copyright (c) 2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - - -#ifdef CONFIG_DRIVER_HOSTAP -extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */ -#endif /* CONFIG_DRIVER_HOSTAP */ -#ifdef CONFIG_DRIVER_NL80211 -extern struct wpa_driver_ops wpa_driver_nl80211_ops; /* driver_nl80211.c */ -#endif /* CONFIG_DRIVER_NL80211 */ -#ifdef CONFIG_DRIVER_PRISM54 -extern struct wpa_driver_ops wpa_driver_prism54_ops; /* driver_prism54.c */ -#endif /* CONFIG_DRIVER_PRISM54 */ -#ifdef CONFIG_DRIVER_MADWIFI -extern struct wpa_driver_ops wpa_driver_madwifi_ops; /* driver_madwifi.c */ -#endif /* CONFIG_DRIVER_MADWIFI */ -#ifdef CONFIG_DRIVER_ATHEROS -extern struct wpa_driver_ops wpa_driver_atheros_ops; /* driver_atheros.c */ -#endif /* CONFIG_DRIVER_ATHEROS */ -#ifdef CONFIG_DRIVER_BSD -extern struct wpa_driver_ops wpa_driver_bsd_ops; /* driver_bsd.c */ -#endif /* CONFIG_DRIVER_BSD */ -#ifdef CONFIG_DRIVER_WIRED -extern struct wpa_driver_ops wpa_driver_wired_ops; /* driver_wired.c */ -#endif /* CONFIG_DRIVER_WIRED */ -#ifdef CONFIG_DRIVER_TEST -extern struct wpa_driver_ops wpa_driver_test_ops; /* driver_test.c */ -#endif /* CONFIG_DRIVER_TEST */ -#ifdef CONFIG_DRIVER_NONE -extern struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */ -#endif /* CONFIG_DRIVER_NONE */ - - -struct wpa_driver_ops *hostapd_drivers[] = -{ -#ifdef CONFIG_DRIVER_HOSTAP - &wpa_driver_hostap_ops, -#endif /* CONFIG_DRIVER_HOSTAP */ -#ifdef CONFIG_DRIVER_NL80211 - &wpa_driver_nl80211_ops, -#endif /* CONFIG_DRIVER_NL80211 */ -#ifdef CONFIG_DRIVER_PRISM54 - &wpa_driver_prism54_ops, -#endif /* CONFIG_DRIVER_PRISM54 */ -#ifdef CONFIG_DRIVER_MADWIFI - &wpa_driver_madwifi_ops, -#endif /* CONFIG_DRIVER_MADWIFI */ -#ifdef CONFIG_DRIVER_ATHEROS - &wpa_driver_atheros_ops, -#endif /* CONFIG_DRIVER_ATHEROS */ -#ifdef CONFIG_DRIVER_BSD - &wpa_driver_bsd_ops, -#endif /* CONFIG_DRIVER_BSD */ -#ifdef CONFIG_DRIVER_WIRED - &wpa_driver_wired_ops, -#endif /* CONFIG_DRIVER_WIRED */ -#ifdef CONFIG_DRIVER_TEST - &wpa_driver_test_ops, -#endif /* CONFIG_DRIVER_TEST */ -#ifdef CONFIG_DRIVER_NONE - &wpa_driver_none_ops, -#endif /* CONFIG_DRIVER_NONE */ - NULL -}; diff --git a/contrib/wpa/hostapd/dump_state.c b/contrib/wpa/hostapd/dump_state.c new file mode 100644 index 000000000000..bba3068ccd81 --- /dev/null +++ b/contrib/wpa/hostapd/dump_state.c @@ -0,0 +1,184 @@ +/* + * hostapd / State dump + * Copyright (c) 2002-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "radius/radius_client.h" +#include "radius/radius_server.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "eapol_auth/eapol_auth_sm_i.h" +#include "eap_server/eap.h" +#include "ap/hostapd.h" +#include "ap/ap_config.h" +#include "ap/sta_info.h" +#include "dump_state.h" + + +static void fprint_char(FILE *f, char c) +{ + if (c >= 32 && c < 127) + fprintf(f, "%c", c); + else + fprintf(f, "<%02x>", c); +} + + +static void ieee802_1x_dump_state(FILE *f, const char *prefix, + struct sta_info *sta) +{ + struct eapol_state_machine *sm = sta->eapol_sm; + if (sm == NULL) + return; + + fprintf(f, "%sIEEE 802.1X:\n", prefix); + + if (sm->identity) { + size_t i; + fprintf(f, "%sidentity=", prefix); + for (i = 0; i < sm->identity_len; i++) + fprint_char(f, sm->identity[i]); + fprintf(f, "\n"); + } + + fprintf(f, "%slast EAP type: Authentication Server: %d (%s) " + "Supplicant: %d (%s)\n", prefix, + sm->eap_type_authsrv, + eap_server_get_name(0, sm->eap_type_authsrv), + sm->eap_type_supp, eap_server_get_name(0, sm->eap_type_supp)); + + fprintf(f, "%scached_packets=%s\n", prefix, + sm->last_recv_radius ? "[RX RADIUS]" : ""); + + eapol_auth_dump_state(f, prefix, sm); +} + + +/** + * hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file + */ +static void hostapd_dump_state(struct hostapd_data *hapd) +{ + FILE *f; + time_t now; + struct sta_info *sta; + int i; +#ifndef CONFIG_NO_RADIUS + char *buf; +#endif /* CONFIG_NO_RADIUS */ + + if (!hapd->conf->dump_log_name) { + wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump " + "request"); + return; + } + + wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'", + hapd->conf->dump_log_name); + f = fopen(hapd->conf->dump_log_name, "w"); + if (f == NULL) { + wpa_printf(MSG_WARNING, "Could not open dump file '%s' for " + "writing.", hapd->conf->dump_log_name); + return; + } + + time(&now); + fprintf(f, "hostapd state dump - %s", ctime(&now)); + fprintf(f, "num_sta=%d num_sta_non_erp=%d " + "num_sta_no_short_slot_time=%d\n" + "num_sta_no_short_preamble=%d\n", + hapd->num_sta, hapd->iface->num_sta_non_erp, + hapd->iface->num_sta_no_short_slot_time, + hapd->iface->num_sta_no_short_preamble); + + for (sta = hapd->sta_list; sta != NULL; sta = sta->next) { + fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr)); + + fprintf(f, + " AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n" + " capability=0x%x listen_interval=%d\n", + sta->aid, + sta->flags, + (sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""), + (sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""), + (sta->flags & WLAN_STA_PS ? "[PS]" : ""), + (sta->flags & WLAN_STA_TIM ? "[TIM]" : ""), + (sta->flags & WLAN_STA_PERM ? "[PERM]" : ""), + (sta->flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : + ""), + (sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" : + ""), + (sta->flags & WLAN_STA_SHORT_PREAMBLE ? + "[SHORT_PREAMBLE]" : ""), + (sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""), + (sta->flags & WLAN_STA_WMM ? "[WMM]" : ""), + (sta->flags & WLAN_STA_MFP ? "[MFP]" : ""), + (sta->flags & WLAN_STA_WPS ? "[WPS]" : ""), + (sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""), + (sta->flags & WLAN_STA_WDS ? "[WDS]" : ""), + (sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""), + sta->capability, + sta->listen_interval); + + fprintf(f, " supported_rates="); + for (i = 0; i < sta->supported_rates_len; i++) + fprintf(f, "%02x ", sta->supported_rates[i]); + fprintf(f, "\n"); + + fprintf(f, + " timeout_next=%s\n", + (sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" : + (sta->timeout_next == STA_DISASSOC ? "DISASSOC" : + "DEAUTH"))); + + ieee802_1x_dump_state(f, " ", sta); + } + +#ifndef CONFIG_NO_RADIUS + buf = os_malloc(4096); + if (buf) { + int count = radius_client_get_mib(hapd->radius, buf, 4096); + if (count < 0) + count = 0; + else if (count > 4095) + count = 4095; + buf[count] = '\0'; + fprintf(f, "%s", buf); + +#ifdef RADIUS_SERVER + count = radius_server_get_mib(hapd->radius_srv, buf, 4096); + if (count < 0) + count = 0; + else if (count > 4095) + count = 4095; + buf[count] = '\0'; + fprintf(f, "%s", buf); +#endif /* RADIUS_SERVER */ + + os_free(buf); + } +#endif /* CONFIG_NO_RADIUS */ + fclose(f); +} + + +int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx) +{ + size_t i; + + for (i = 0; i < iface->num_bss; i++) + hostapd_dump_state(iface->bss[i]); + + return 0; +} diff --git a/contrib/wpa/hostapd/dump_state.h b/contrib/wpa/hostapd/dump_state.h new file mode 100644 index 000000000000..e14f08a4f5e1 --- /dev/null +++ b/contrib/wpa/hostapd/dump_state.h @@ -0,0 +1,20 @@ +/* + * hostapd / State dump + * Copyright (c) 2002-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef DUMP_STATE_H +#define DUMP_STATE_H + +int handle_dump_state_iface(struct hostapd_iface *iface, void *ctx); + +#endif /* DUMP_STATE_H */ diff --git a/contrib/wpa/hostapd/eap_register.c b/contrib/wpa/hostapd/eap_register.c new file mode 100644 index 000000000000..ae9bf9d38de9 --- /dev/null +++ b/contrib/wpa/hostapd/eap_register.c @@ -0,0 +1,134 @@ +/* + * EAP method registration + * Copyright (c) 2004-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "eap_server/eap_methods.h" +#include "eap_register.h" + + +/** + * eap_server_register_methods - Register statically linked EAP server methods + * Returns: 0 on success, -1 or -2 on failure + * + * This function is called at program initialization to register all EAP + * methods that were linked in statically. + */ +int eap_server_register_methods(void) +{ + int ret = 0; + +#ifdef EAP_SERVER_IDENTITY + if (ret == 0) + ret = eap_server_identity_register(); +#endif /* EAP_SERVER_IDENTITY */ + +#ifdef EAP_SERVER_MD5 + if (ret == 0) + ret = eap_server_md5_register(); +#endif /* EAP_SERVER_MD5 */ + +#ifdef EAP_SERVER_TLS + if (ret == 0) + ret = eap_server_tls_register(); +#endif /* EAP_SERVER_TLS */ + +#ifdef EAP_SERVER_MSCHAPV2 + if (ret == 0) + ret = eap_server_mschapv2_register(); +#endif /* EAP_SERVER_MSCHAPV2 */ + +#ifdef EAP_SERVER_PEAP + if (ret == 0) + ret = eap_server_peap_register(); +#endif /* EAP_SERVER_PEAP */ + +#ifdef EAP_SERVER_TLV + if (ret == 0) + ret = eap_server_tlv_register(); +#endif /* EAP_SERVER_TLV */ + +#ifdef EAP_SERVER_GTC + if (ret == 0) + ret = eap_server_gtc_register(); +#endif /* EAP_SERVER_GTC */ + +#ifdef EAP_SERVER_TTLS + if (ret == 0) + ret = eap_server_ttls_register(); +#endif /* EAP_SERVER_TTLS */ + +#ifdef EAP_SERVER_SIM + if (ret == 0) + ret = eap_server_sim_register(); +#endif /* EAP_SERVER_SIM */ + +#ifdef EAP_SERVER_AKA + if (ret == 0) + ret = eap_server_aka_register(); +#endif /* EAP_SERVER_AKA */ + +#ifdef EAP_SERVER_AKA_PRIME + if (ret == 0) + ret = eap_server_aka_prime_register(); +#endif /* EAP_SERVER_AKA_PRIME */ + +#ifdef EAP_SERVER_PAX + if (ret == 0) + ret = eap_server_pax_register(); +#endif /* EAP_SERVER_PAX */ + +#ifdef EAP_SERVER_PSK + if (ret == 0) + ret = eap_server_psk_register(); +#endif /* EAP_SERVER_PSK */ + +#ifdef EAP_SERVER_SAKE + if (ret == 0) + ret = eap_server_sake_register(); +#endif /* EAP_SERVER_SAKE */ + +#ifdef EAP_SERVER_GPSK + if (ret == 0) + ret = eap_server_gpsk_register(); +#endif /* EAP_SERVER_GPSK */ + +#ifdef EAP_SERVER_VENDOR_TEST + if (ret == 0) + ret = eap_server_vendor_test_register(); +#endif /* EAP_SERVER_VENDOR_TEST */ + +#ifdef EAP_SERVER_FAST + if (ret == 0) + ret = eap_server_fast_register(); +#endif /* EAP_SERVER_FAST */ + +#ifdef EAP_SERVER_WSC + if (ret == 0) + ret = eap_server_wsc_register(); +#endif /* EAP_SERVER_WSC */ + +#ifdef EAP_SERVER_IKEV2 + if (ret == 0) + ret = eap_server_ikev2_register(); +#endif /* EAP_SERVER_IKEV2 */ + +#ifdef EAP_SERVER_TNC + if (ret == 0) + ret = eap_server_tnc_register(); +#endif /* EAP_SERVER_TNC */ + + return ret; +} diff --git a/contrib/wpa/src/crypto/rc4.h b/contrib/wpa/hostapd/eap_register.h similarity index 61% rename from contrib/wpa/src/crypto/rc4.h rename to contrib/wpa/hostapd/eap_register.h index 35c7e41fba06..82e7171d6fde 100644 --- a/contrib/wpa/src/crypto/rc4.h +++ b/contrib/wpa/hostapd/eap_register.h @@ -1,6 +1,6 @@ /* - * RC4 stream cipher - * Copyright (c) 2002-2005, Jouni Malinen + * EAP method registration + * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,10 +12,9 @@ * See README and COPYING for more details. */ -#ifndef RC4_H -#define RC4_H +#ifndef EAP_REGISTER_H +#define EAP_REGISTER_H -void rc4_skip(const u8 *key, size_t keylen, size_t skip, - u8 *data, size_t data_len); +int eap_server_register_methods(void); -#endif /* RC4_H */ +#endif /* EAP_REGISTER_H */ diff --git a/contrib/wpa/src/hlr_auc_gw/hlr_auc_gw.c b/contrib/wpa/hostapd/hlr_auc_gw.c similarity index 99% rename from contrib/wpa/src/hlr_auc_gw/hlr_auc_gw.c rename to contrib/wpa/hostapd/hlr_auc_gw.c index e318903543ad..36934aa9728a 100644 --- a/contrib/wpa/src/hlr_auc_gw/hlr_auc_gw.c +++ b/contrib/wpa/hostapd/hlr_auc_gw.c @@ -47,7 +47,7 @@ #include #include "common.h" -#include "milenage.h" +#include "crypto/milenage.h" static const char *default_socket_path = "/tmp/hlr_auc_gw.sock"; static const char *socket_path; diff --git a/contrib/wpa/src/hlr_auc_gw/hlr_auc_gw.milenage_db b/contrib/wpa/hostapd/hlr_auc_gw.milenage_db similarity index 100% rename from contrib/wpa/src/hlr_auc_gw/hlr_auc_gw.milenage_db rename to contrib/wpa/hostapd/hlr_auc_gw.milenage_db diff --git a/contrib/wpa/hostapd/hostap_common.h b/contrib/wpa/hostapd/hostap_common.h deleted file mode 100644 index 5a57dca46d3e..000000000000 --- a/contrib/wpa/hostapd/hostap_common.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * hostapd / Kernel driver communication with Linux Host AP driver - * Copyright (c) 2002-2006, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HOSTAP_COMMON_H -#define HOSTAP_COMMON_H - -/* netdevice private ioctls (used, e.g., with iwpriv from user space) */ - -/* New wireless extensions API - SET/GET convention (even ioctl numbers are - * root only) - */ -#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0) -#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1) -#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2) -#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3) -#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4) -#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6) -#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8) -#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10) -#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12) -#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14) -#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16) -#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18) -#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20) -#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22) - -/* following are not in SIOCGIWPRIV list; check permission in the driver code - */ -#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13) -#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14) - - -/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */ -enum { - /* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */ - PRISM2_PARAM_TXRATECTRL = 2, - PRISM2_PARAM_BEACON_INT = 3, - PRISM2_PARAM_PSEUDO_IBSS = 4, - PRISM2_PARAM_ALC = 5, - /* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */ - PRISM2_PARAM_DUMP = 7, - PRISM2_PARAM_OTHER_AP_POLICY = 8, - PRISM2_PARAM_AP_MAX_INACTIVITY = 9, - PRISM2_PARAM_AP_BRIDGE_PACKETS = 10, - PRISM2_PARAM_DTIM_PERIOD = 11, - PRISM2_PARAM_AP_NULLFUNC_ACK = 12, - PRISM2_PARAM_MAX_WDS = 13, - PRISM2_PARAM_AP_AUTOM_AP_WDS = 14, - PRISM2_PARAM_AP_AUTH_ALGS = 15, - PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16, - PRISM2_PARAM_HOST_ENCRYPT = 17, - PRISM2_PARAM_HOST_DECRYPT = 18, - PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19, - PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20, - PRISM2_PARAM_HOST_ROAMING = 21, - PRISM2_PARAM_BCRX_STA_KEY = 22, - PRISM2_PARAM_IEEE_802_1X = 23, - PRISM2_PARAM_ANTSEL_TX = 24, - PRISM2_PARAM_ANTSEL_RX = 25, - PRISM2_PARAM_MONITOR_TYPE = 26, - PRISM2_PARAM_WDS_TYPE = 27, - PRISM2_PARAM_HOSTSCAN = 28, - PRISM2_PARAM_AP_SCAN = 29, - PRISM2_PARAM_ENH_SEC = 30, - PRISM2_PARAM_IO_DEBUG = 31, - PRISM2_PARAM_BASIC_RATES = 32, - PRISM2_PARAM_OPER_RATES = 33, - PRISM2_PARAM_HOSTAPD = 34, - PRISM2_PARAM_HOSTAPD_STA = 35, - PRISM2_PARAM_WPA = 36, - PRISM2_PARAM_PRIVACY_INVOKED = 37, - PRISM2_PARAM_TKIP_COUNTERMEASURES = 38, - PRISM2_PARAM_DROP_UNENCRYPTED = 39, - PRISM2_PARAM_SCAN_CHANNEL_MASK = 40, -}; - -enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1, - HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 }; - - -/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */ -enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1, - AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3, - AP_MAC_CMD_KICKALL = 4 }; - - -/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */ -enum { - PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */, - /* Note! Old versions of prism2_srec have a fatal error in CRC-16 - * calculation, which will corrupt all non-volatile downloads. - * PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to - * prevent use of old versions of prism2_srec for non-volatile - * download. */ - PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */, - PRISM2_DOWNLOAD_VOLATILE_GENESIS = 4 /* RAM in Genesis mode */, - /* Persistent versions of volatile download commands (keep firmware - * data in memory and automatically re-download after hw_reset */ - PRISM2_DOWNLOAD_VOLATILE_PERSISTENT = 5, - PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT = 6, -}; - -struct prism2_download_param { - u32 dl_cmd; - u32 start_addr; - u32 num_areas; - struct prism2_download_area { - u32 addr; /* wlan card address */ - u32 len; - caddr_t ptr; /* pointer to data in user space */ - } data[0]; -}; - -#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072 -#define PRISM2_MAX_DOWNLOAD_LEN 262144 - - -/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */ -enum { - PRISM2_HOSTAPD_FLUSH = 1, - PRISM2_HOSTAPD_ADD_STA = 2, - PRISM2_HOSTAPD_REMOVE_STA = 3, - PRISM2_HOSTAPD_GET_INFO_STA = 4, - /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */ - PRISM2_SET_ENCRYPTION = 6, - PRISM2_GET_ENCRYPTION = 7, - PRISM2_HOSTAPD_SET_FLAGS_STA = 8, - PRISM2_HOSTAPD_GET_RID = 9, - PRISM2_HOSTAPD_SET_RID = 10, - PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11, - PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12, - PRISM2_HOSTAPD_MLME = 13, - PRISM2_HOSTAPD_SCAN_REQ = 14, - PRISM2_HOSTAPD_STA_CLEAR_STATS = 15, -}; - -#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 -#define PRISM2_HOSTAPD_RID_HDR_LEN \ -((size_t) (&((struct prism2_hostapd_param *) 0)->u.rid.data)) -#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ -((size_t) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data)) - -/* Maximum length for algorithm names (-1 for nul termination) used in ioctl() - */ -#define HOSTAP_CRYPT_ALG_NAME_LEN 16 - - -struct prism2_hostapd_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u16 aid; - u16 capability; - u8 tx_supp_rates; - } add_sta; - struct { - u32 inactive_sec; - } get_info_sta; - struct { - u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; - u32 flags; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[0]; - } crypt; - struct { - u32 flags_and; - u32 flags_or; - } set_flags_sta; - struct { - u16 rid; - u16 len; - u8 data[0]; - } rid; - struct { - u8 len; - u8 data[0]; - } generic_elem; - struct { -#define MLME_STA_DEAUTH 0 -#define MLME_STA_DISASSOC 1 - u16 cmd; - u16 reason_code; - } mlme; - struct { - u8 ssid_len; - u8 ssid[32]; - } scan_req; - } u; -}; - -#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0) -#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1) - -#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 -#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 -#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4 -#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 -#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7 - -#endif /* HOSTAP_COMMON_H */ diff --git a/contrib/wpa/hostapd/hostapd.8 b/contrib/wpa/hostapd/hostapd.8 index a67a1bcca6c7..b4456bbcf3e6 100644 --- a/contrib/wpa/hostapd/hostapd.8 +++ b/contrib/wpa/hostapd/hostapd.8 @@ -12,7 +12,7 @@ daemon. .B hostapd is a user space daemon for access point and authentication servers. It implements IEEE 802.11 access point management, IEEE 802.1X/WPA/WPA2/EAP Authenticators and RADIUS authentication server. -The current version supports Linux (Host AP, madwifi, Prism54 drivers) and FreeBSD (net80211). +The current version supports Linux (Host AP, madwifi, mac80211-based drivers) and FreeBSD (net80211). .B hostapd is designed to be a "daemon" program that runs in the background and acts as the backend component controlling authentication. diff --git a/contrib/wpa/hostapd/hostapd.c b/contrib/wpa/hostapd/hostapd.c deleted file mode 100644 index b1c5a2c31598..000000000000 --- a/contrib/wpa/hostapd/hostapd.c +++ /dev/null @@ -1,2043 +0,0 @@ -/* - * hostapd / Initialization and configuration - * Copyright (c) 2002-2009, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" -#ifndef CONFIG_NATIVE_WINDOWS -#include -#endif /* CONFIG_NATIVE_WINDOWS */ - -#include "eloop.h" -#include "hostapd.h" -#include "ieee802_1x.h" -#include "ieee802_11.h" -#include "beacon.h" -#include "hw_features.h" -#include "accounting.h" -#include "eapol_sm.h" -#include "iapp.h" -#include "ap.h" -#include "ieee802_11_auth.h" -#include "ap_list.h" -#include "sta_info.h" -#include "driver.h" -#include "radius/radius_client.h" -#include "radius/radius_server.h" -#include "wpa.h" -#include "preauth.h" -#include "wme.h" -#include "vlan_init.h" -#include "ctrl_iface.h" -#include "tls.h" -#include "eap_server/eap_sim_db.h" -#include "eap_server/eap.h" -#include "eap_server/tncs.h" -#include "version.h" -#include "l2_packet/l2_packet.h" -#include "wps_hostapd.h" - - -static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity, - size_t identity_len, int phase2, - struct eap_user *user); -static int hostapd_flush_old_stations(struct hostapd_data *hapd); -static int hostapd_setup_wpa(struct hostapd_data *hapd); -static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd); - -struct hapd_interfaces { - size_t count; - struct hostapd_iface **iface; -}; - -unsigned char rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - - -extern int wpa_debug_level; -extern int wpa_debug_show_keys; -extern int wpa_debug_timestamp; - - -static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, - int level, const char *txt, size_t len) -{ - struct hostapd_data *hapd = ctx; - char *format, *module_str; - int maxlen; - int conf_syslog_level, conf_stdout_level; - unsigned int conf_syslog, conf_stdout; - - maxlen = len + 100; - format = os_malloc(maxlen); - if (!format) - return; - - if (hapd && hapd->conf) { - conf_syslog_level = hapd->conf->logger_syslog_level; - conf_stdout_level = hapd->conf->logger_stdout_level; - conf_syslog = hapd->conf->logger_syslog; - conf_stdout = hapd->conf->logger_stdout; - } else { - conf_syslog_level = conf_stdout_level = 0; - conf_syslog = conf_stdout = (unsigned int) -1; - } - - switch (module) { - case HOSTAPD_MODULE_IEEE80211: - module_str = "IEEE 802.11"; - break; - case HOSTAPD_MODULE_IEEE8021X: - module_str = "IEEE 802.1X"; - break; - case HOSTAPD_MODULE_RADIUS: - module_str = "RADIUS"; - break; - case HOSTAPD_MODULE_WPA: - module_str = "WPA"; - break; - case HOSTAPD_MODULE_DRIVER: - module_str = "DRIVER"; - break; - case HOSTAPD_MODULE_IAPP: - module_str = "IAPP"; - break; - case HOSTAPD_MODULE_MLME: - module_str = "MLME"; - break; - default: - module_str = NULL; - break; - } - - if (hapd && hapd->conf && addr) - os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s", - hapd->conf->iface, MAC2STR(addr), - module_str ? " " : "", module_str, txt); - else if (hapd && hapd->conf) - os_snprintf(format, maxlen, "%s:%s%s %s", - hapd->conf->iface, module_str ? " " : "", - module_str, txt); - else if (addr) - os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s", - MAC2STR(addr), module_str ? " " : "", - module_str, txt); - else - os_snprintf(format, maxlen, "%s%s%s", - module_str, module_str ? ": " : "", txt); - - if ((conf_stdout & module) && level >= conf_stdout_level) { - wpa_debug_print_timestamp(); - printf("%s\n", format); - } - -#ifndef CONFIG_NATIVE_WINDOWS - if ((conf_syslog & module) && level >= conf_syslog_level) { - int priority; - switch (level) { - case HOSTAPD_LEVEL_DEBUG_VERBOSE: - case HOSTAPD_LEVEL_DEBUG: - priority = LOG_DEBUG; - break; - case HOSTAPD_LEVEL_INFO: - priority = LOG_INFO; - break; - case HOSTAPD_LEVEL_NOTICE: - priority = LOG_NOTICE; - break; - case HOSTAPD_LEVEL_WARNING: - priority = LOG_WARNING; - break; - default: - priority = LOG_INFO; - break; - } - syslog(priority, "%s", format); - } -#endif /* CONFIG_NATIVE_WINDOWS */ - - os_free(format); -} - - -static void hostapd_deauth_all_stas(struct hostapd_data *hapd) -{ - u8 addr[ETH_ALEN]; - - /* New Prism2.5/3 STA firmware versions seem to have issues with this - * broadcast deauth frame. This gets the firmware in odd state where - * nothing works correctly, so let's skip sending this for the hostap - * driver. */ - - if (hapd->driver && os_strcmp(hapd->driver->name, "hostap") != 0) { - os_memset(addr, 0xff, ETH_ALEN); - hostapd_sta_deauth(hapd, addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); - } -} - - -/** - * hostapd_prune_associations - Remove extraneous associations - * @hapd: Pointer to BSS data for the most recent association - * @sta: Pointer to the associated STA data - * - * This function looks through all radios and BSS's for previous - * (stale) associations of STA. If any are found they are removed. - */ -static void hostapd_prune_associations(struct hostapd_data *hapd, - struct sta_info *sta) -{ - struct sta_info *osta; - struct hostapd_data *ohapd; - size_t i, j; - struct hapd_interfaces *interfaces = eloop_get_user_data(); - - for (i = 0; i < interfaces->count; i++) { - for (j = 0; j < interfaces->iface[i]->num_bss; j++) { - ohapd = interfaces->iface[i]->bss[j]; - if (ohapd == hapd) - continue; - osta = ap_get_sta(ohapd, sta->addr); - if (!osta) - continue; - - ap_sta_disassociate(ohapd, osta, - WLAN_REASON_UNSPECIFIED); - } - } -} - - -/** - * hostapd_new_assoc_sta - Notify that a new station associated with the AP - * @hapd: Pointer to BSS data - * @sta: Pointer to the associated STA data - * @reassoc: 1 to indicate this was a re-association; 0 = first association - * - * This function will be called whenever a station associates with the AP. It - * can be called for ieee802_11.c for drivers that export MLME to hostapd and - * from driver_*.c for drivers that take care of management frames (IEEE 802.11 - * authentication and association) internally. - */ -void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, - int reassoc) -{ - if (hapd->tkip_countermeasures) { - hostapd_sta_deauth(hapd, sta->addr, - WLAN_REASON_MICHAEL_MIC_FAILURE); - return; - } - - hostapd_prune_associations(hapd, sta); - - /* IEEE 802.11F (IAPP) */ - if (hapd->conf->ieee802_11f) - iapp_new_station(hapd->iapp, sta); - - /* Start accounting here, if IEEE 802.1X and WPA are not used. - * IEEE 802.1X/WPA code will start accounting after the station has - * been authorized. */ - if (!hapd->conf->ieee802_1x && !hapd->conf->wpa) - accounting_sta_start(hapd, sta); - - hostapd_wmm_sta_config(hapd, sta); - - /* Start IEEE 802.1X authentication process for new stations */ - ieee802_1x_new_station(hapd, sta); - if (reassoc) { - if (sta->auth_alg != WLAN_AUTH_FT && - !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) - wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH); - } else - wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm); -} - - -#ifdef EAP_SERVER -static int hostapd_sim_db_cb_sta(struct hostapd_data *hapd, - struct sta_info *sta, void *ctx) -{ - if (eapol_auth_eap_pending_cb(sta->eapol_sm, ctx) == 0) - return 1; - return 0; -} - - -static void hostapd_sim_db_cb(void *ctx, void *session_ctx) -{ - struct hostapd_data *hapd = ctx; - if (ap_for_each_sta(hapd, hostapd_sim_db_cb_sta, session_ctx) == 0) - radius_server_eap_pending_cb(hapd->radius_srv, session_ctx); -} -#endif /* EAP_SERVER */ - - -/** - * handle_term - SIGINT and SIGTERM handler to terminate hostapd process - */ -static void handle_term(int sig, void *eloop_ctx, void *signal_ctx) -{ - wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig); - eloop_terminate(); -} - - -static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, - struct wpa_auth_config *wconf) -{ - wconf->wpa = conf->wpa; - wconf->wpa_key_mgmt = conf->wpa_key_mgmt; - wconf->wpa_pairwise = conf->wpa_pairwise; - wconf->wpa_group = conf->wpa_group; - wconf->wpa_group_rekey = conf->wpa_group_rekey; - wconf->wpa_strict_rekey = conf->wpa_strict_rekey; - wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey; - wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey; - wconf->rsn_pairwise = conf->rsn_pairwise; - wconf->rsn_preauth = conf->rsn_preauth; - wconf->eapol_version = conf->eapol_version; - wconf->peerkey = conf->peerkey; - wconf->wmm_enabled = conf->wmm_enabled; - wconf->okc = conf->okc; -#ifdef CONFIG_IEEE80211W - wconf->ieee80211w = conf->ieee80211w; -#endif /* CONFIG_IEEE80211W */ -#ifdef CONFIG_IEEE80211R - wconf->ssid_len = conf->ssid.ssid_len; - if (wconf->ssid_len > SSID_LEN) - wconf->ssid_len = SSID_LEN; - os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len); - os_memcpy(wconf->mobility_domain, conf->mobility_domain, - MOBILITY_DOMAIN_ID_LEN); - if (conf->nas_identifier && - os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) { - wconf->r0_key_holder_len = os_strlen(conf->nas_identifier); - os_memcpy(wconf->r0_key_holder, conf->nas_identifier, - wconf->r0_key_holder_len); - } - os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN); - wconf->r0_key_lifetime = conf->r0_key_lifetime; - wconf->reassociation_deadline = conf->reassociation_deadline; - wconf->r0kh_list = conf->r0kh_list; - wconf->r1kh_list = conf->r1kh_list; - wconf->pmk_r1_push = conf->pmk_r1_push; -#endif /* CONFIG_IEEE80211R */ -} - - -int hostapd_reload_config(struct hostapd_iface *iface) -{ - struct hostapd_data *hapd = iface->bss[0]; - struct hostapd_config *newconf, *oldconf; - struct wpa_auth_config wpa_auth_conf; - size_t j; - - newconf = hostapd_config_read(iface->config_fname); - if (newconf == NULL) - return -1; - - /* - * Deauthenticate all stations since the new configuration may not - * allow them to use the BSS anymore. - */ - for (j = 0; j < iface->num_bss; j++) - hostapd_flush_old_stations(iface->bss[j]); - - /* TODO: update dynamic data based on changed configuration - * items (e.g., open/close sockets, etc.) */ - radius_client_flush(hapd->radius, 0); - - oldconf = hapd->iconf; - hapd->iconf = newconf; - hapd->conf = &newconf->bss[0]; - iface->conf = newconf; - - if (hostapd_setup_wpa_psk(hapd->conf)) { - wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK " - "after reloading configuration"); - } - - if (hapd->conf->wpa && hapd->wpa_auth == NULL) - hostapd_setup_wpa(hapd); - else if (hapd->conf->wpa) { - hostapd_wpa_auth_conf(&newconf->bss[0], &wpa_auth_conf); - wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf); - } else if (hapd->wpa_auth) { - wpa_deinit(hapd->wpa_auth); - hapd->wpa_auth = NULL; - hostapd_set_privacy(hapd, 0); - hostapd_setup_encryption(hapd->conf->iface, hapd); - } - - ieee802_11_set_beacon(hapd); - - if (hapd->conf->ssid.ssid_set && - hostapd_set_ssid(hapd, (u8 *) hapd->conf->ssid.ssid, - hapd->conf->ssid.ssid_len)) { - wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); - /* try to continue */ - } - - if (hapd->conf->ieee802_1x || hapd->conf->wpa) - hostapd_set_ieee8021x(hapd->conf->iface, hapd, 1); - - hostapd_config_free(oldconf); - - wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface); - - return 0; -} - - -#ifndef CONFIG_NATIVE_WINDOWS -/** - * handle_reload - SIGHUP handler to reload configuration - */ -static void handle_reload(int sig, void *eloop_ctx, void *signal_ctx) -{ - struct hapd_interfaces *hapds = (struct hapd_interfaces *) eloop_ctx; - size_t i; - - wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration", - sig); - - for (i = 0; i < hapds->count; i++) { - if (hostapd_reload_config(hapds->iface[i]) < 0) { - wpa_printf(MSG_WARNING, "Failed to read new " - "configuration file - continuing with " - "old."); - continue; - } - } -} - - -#ifdef HOSTAPD_DUMP_STATE -/** - * hostapd_dump_state - SIGUSR1 handler to dump hostapd state to a text file - */ -static void hostapd_dump_state(struct hostapd_data *hapd) -{ - FILE *f; - time_t now; - struct sta_info *sta; - int i; - char *buf; - - if (!hapd->conf->dump_log_name) { - wpa_printf(MSG_DEBUG, "Dump file not defined - ignoring dump " - "request"); - return; - } - - wpa_printf(MSG_DEBUG, "Dumping hostapd state to '%s'", - hapd->conf->dump_log_name); - f = fopen(hapd->conf->dump_log_name, "w"); - if (f == NULL) { - wpa_printf(MSG_WARNING, "Could not open dump file '%s' for " - "writing.", hapd->conf->dump_log_name); - return; - } - - time(&now); - fprintf(f, "hostapd state dump - %s", ctime(&now)); - fprintf(f, "num_sta=%d num_sta_non_erp=%d " - "num_sta_no_short_slot_time=%d\n" - "num_sta_no_short_preamble=%d\n", - hapd->num_sta, hapd->iface->num_sta_non_erp, - hapd->iface->num_sta_no_short_slot_time, - hapd->iface->num_sta_no_short_preamble); - - for (sta = hapd->sta_list; sta != NULL; sta = sta->next) { - fprintf(f, "\nSTA=" MACSTR "\n", MAC2STR(sta->addr)); - - fprintf(f, - " AID=%d flags=0x%x %s%s%s%s%s%s%s%s%s%s%s%s%s%s\n" - " capability=0x%x listen_interval=%d\n", - sta->aid, - sta->flags, - (sta->flags & WLAN_STA_AUTH ? "[AUTH]" : ""), - (sta->flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""), - (sta->flags & WLAN_STA_PS ? "[PS]" : ""), - (sta->flags & WLAN_STA_TIM ? "[TIM]" : ""), - (sta->flags & WLAN_STA_PERM ? "[PERM]" : ""), - (sta->flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : - ""), - (sta->flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" : - ""), - (sta->flags & WLAN_STA_SHORT_PREAMBLE ? - "[SHORT_PREAMBLE]" : ""), - (sta->flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""), - (sta->flags & WLAN_STA_WMM ? "[WMM]" : ""), - (sta->flags & WLAN_STA_MFP ? "[MFP]" : ""), - (sta->flags & WLAN_STA_WPS ? "[WPS]" : ""), - (sta->flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""), - (sta->flags & WLAN_STA_NONERP ? "[NonERP]" : ""), - sta->capability, - sta->listen_interval); - - fprintf(f, " supported_rates="); - for (i = 0; i < sta->supported_rates_len; i++) - fprintf(f, "%02x ", sta->supported_rates[i]); - fprintf(f, "\n"); - - fprintf(f, - " timeout_next=%s\n", - (sta->timeout_next == STA_NULLFUNC ? "NULLFUNC POLL" : - (sta->timeout_next == STA_DISASSOC ? "DISASSOC" : - "DEAUTH"))); - - ieee802_1x_dump_state(f, " ", sta); - } - - buf = os_malloc(4096); - if (buf) { - int count = radius_client_get_mib(hapd->radius, buf, 4096); - if (count < 0) - count = 0; - else if (count > 4095) - count = 4095; - buf[count] = '\0'; - fprintf(f, "%s", buf); - - count = radius_server_get_mib(hapd->radius_srv, buf, 4096); - if (count < 0) - count = 0; - else if (count > 4095) - count = 4095; - buf[count] = '\0'; - fprintf(f, "%s", buf); - os_free(buf); - } - fclose(f); -} -#endif /* HOSTAPD_DUMP_STATE */ - - -static void handle_dump_state(int sig, void *eloop_ctx, void *signal_ctx) -{ -#ifdef HOSTAPD_DUMP_STATE - struct hapd_interfaces *hapds = (struct hapd_interfaces *) eloop_ctx; - size_t i, j; - - for (i = 0; i < hapds->count; i++) { - struct hostapd_iface *hapd_iface = hapds->iface[i]; - for (j = 0; j < hapd_iface->num_bss; j++) - hostapd_dump_state(hapd_iface->bss[j]); - } -#endif /* HOSTAPD_DUMP_STATE */ -} -#endif /* CONFIG_NATIVE_WINDOWS */ - -static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd, - char *ifname) -{ - int i; - - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (hostapd_set_encryption(ifname, hapd, "none", NULL, i, NULL, - 0, i == 0 ? 1 : 0)) { - wpa_printf(MSG_DEBUG, "Failed to clear default " - "encryption keys (ifname=%s keyidx=%d)", - ifname, i); - } - } -#ifdef CONFIG_IEEE80211W - if (hapd->conf->ieee80211w) { - for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) { - if (hostapd_set_encryption(ifname, hapd, "none", NULL, - i, NULL, 0, - i == 0 ? 1 : 0)) { - wpa_printf(MSG_DEBUG, "Failed to clear " - "default mgmt encryption keys " - "(ifname=%s keyidx=%d)", ifname, i); - } - } - } -#endif /* CONFIG_IEEE80211W */ -} - - -static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd) -{ - hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface); - return 0; -} - - -static int hostapd_broadcast_wep_set(struct hostapd_data *hapd) -{ - int errors = 0, idx; - struct hostapd_ssid *ssid = &hapd->conf->ssid; - - idx = ssid->wep.idx; - if (ssid->wep.default_len && - hostapd_set_encryption(hapd->conf->iface, - hapd, "WEP", NULL, idx, - ssid->wep.key[idx], - ssid->wep.len[idx], - idx == ssid->wep.idx)) { - wpa_printf(MSG_WARNING, "Could not set WEP encryption."); - errors++; - } - - if (ssid->dyn_vlan_keys) { - size_t i; - for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) { - const char *ifname; - struct hostapd_wep_keys *key = ssid->dyn_vlan_keys[i]; - if (key == NULL) - continue; - ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, - i); - if (ifname == NULL) - continue; - - idx = key->idx; - if (hostapd_set_encryption(ifname, hapd, "WEP", NULL, - idx, key->key[idx], - key->len[idx], - idx == key->idx)) { - wpa_printf(MSG_WARNING, "Could not set " - "dynamic VLAN WEP encryption."); - errors++; - } - } - } - - return errors; -} - -/** - * hostapd_cleanup - Per-BSS cleanup (deinitialization) - * @hapd: Pointer to BSS data - * - * This function is used to free all per-BSS data structures and resources. - * This gets called in a loop for each BSS between calls to - * hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface - * is deinitialized. Most of the modules that are initialized in - * hostapd_setup_bss() are deinitialized here. - */ -static void hostapd_cleanup(struct hostapd_data *hapd) -{ - hostapd_ctrl_iface_deinit(hapd); - - os_free(hapd->default_wep_key); - hapd->default_wep_key = NULL; - iapp_deinit(hapd->iapp); - hapd->iapp = NULL; - accounting_deinit(hapd); - rsn_preauth_iface_deinit(hapd); - if (hapd->wpa_auth) { - wpa_deinit(hapd->wpa_auth); - hapd->wpa_auth = NULL; - - if (hostapd_set_privacy(hapd, 0)) { - wpa_printf(MSG_DEBUG, "Could not disable " - "PrivacyInvoked for interface %s", - hapd->conf->iface); - } - - if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) { - wpa_printf(MSG_DEBUG, "Could not remove generic " - "information element from interface %s", - hapd->conf->iface); - } - } - ieee802_1x_deinit(hapd); - vlan_deinit(hapd); - hostapd_acl_deinit(hapd); - radius_client_deinit(hapd->radius); - hapd->radius = NULL; - radius_server_deinit(hapd->radius_srv); - hapd->radius_srv = NULL; - -#ifdef CONFIG_IEEE80211R - l2_packet_deinit(hapd->l2); -#endif /* CONFIG_IEEE80211R */ - - hostapd_deinit_wps(hapd); - - hostapd_wireless_event_deinit(hapd); - -#ifdef EAP_TLS_FUNCS - if (hapd->ssl_ctx) { - tls_deinit(hapd->ssl_ctx); - hapd->ssl_ctx = NULL; - } -#endif /* EAP_TLS_FUNCS */ - -#ifdef EAP_SERVER - if (hapd->eap_sim_db_priv) { - eap_sim_db_deinit(hapd->eap_sim_db_priv); - hapd->eap_sim_db_priv = NULL; - } -#endif /* EAP_SERVER */ - - if (hapd->interface_added && - hostapd_bss_remove(hapd, hapd->conf->iface)) { - wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s", - hapd->conf->iface); - } -} - - -/** - * hostapd_cleanup_iface_pre - Preliminary per-interface cleanup - * @iface: Pointer to interface data - * - * This function is called before per-BSS data structures are deinitialized - * with hostapd_cleanup(). - */ -static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface) -{ -} - - -/** - * hostapd_cleanup_iface - Complete per-interface cleanup - * @iface: Pointer to interface data - * - * This function is called after per-BSS data structures are deinitialized - * with hostapd_cleanup(). - */ -static void hostapd_cleanup_iface(struct hostapd_iface *iface) -{ - hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); - iface->hw_features = NULL; - os_free(iface->current_rates); - iface->current_rates = NULL; - ap_list_deinit(iface); - hostapd_config_free(iface->conf); - iface->conf = NULL; - - os_free(iface->config_fname); - os_free(iface->bss); - os_free(iface); -} - - -static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd) -{ - int i; - - hostapd_broadcast_wep_set(hapd); - - if (hapd->conf->ssid.wep.default_len) - return 0; - - for (i = 0; i < 4; i++) { - if (hapd->conf->ssid.wep.key[i] && - hostapd_set_encryption(iface, hapd, "WEP", NULL, - i, hapd->conf->ssid.wep.key[i], - hapd->conf->ssid.wep.len[i], - i == hapd->conf->ssid.wep.idx)) { - wpa_printf(MSG_WARNING, "Could not set WEP " - "encryption."); - return -1; - } - if (hapd->conf->ssid.wep.key[i] && - i == hapd->conf->ssid.wep.idx) - hostapd_set_privacy(hapd, 1); - } - - return 0; -} - - -static int hostapd_flush_old_stations(struct hostapd_data *hapd) -{ - int ret = 0; - - if (hostapd_drv_none(hapd)) - return 0; - - wpa_printf(MSG_DEBUG, "Flushing old station entries"); - if (hostapd_flush(hapd)) { - wpa_printf(MSG_WARNING, "Could not connect to kernel driver."); - ret = -1; - } - wpa_printf(MSG_DEBUG, "Deauthenticate all stations"); - hostapd_deauth_all_stas(hapd); - - return ret; -} - - -static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr, - logger_level level, const char *txt) -{ - struct hostapd_data *hapd = ctx; - int hlevel; - - switch (level) { - case LOGGER_WARNING: - hlevel = HOSTAPD_LEVEL_WARNING; - break; - case LOGGER_INFO: - hlevel = HOSTAPD_LEVEL_INFO; - break; - case LOGGER_DEBUG: - default: - hlevel = HOSTAPD_LEVEL_DEBUG; - break; - } - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt); -} - - -static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr, - u16 reason) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - - wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: " - "STA " MACSTR " reason %d", - __func__, MAC2STR(addr), reason); - - sta = ap_get_sta(hapd, addr); - hostapd_sta_deauth(hapd, addr, reason); - if (sta == NULL) - return; - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED); - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta); - sta->timeout_next = STA_REMOVE; -} - - -static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) -{ - struct hostapd_data *hapd = ctx; - ieee80211_michael_mic_failure(hapd, addr, 0); -} - - -static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr, - wpa_eapol_variable var, int value) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = ap_get_sta(hapd, addr); - if (sta == NULL) - return; - switch (var) { - case WPA_EAPOL_portEnabled: - ieee802_1x_notify_port_enabled(sta->eapol_sm, value); - break; - case WPA_EAPOL_portValid: - ieee802_1x_notify_port_valid(sta->eapol_sm, value); - break; - case WPA_EAPOL_authorized: - ieee802_1x_set_sta_authorized(hapd, sta, value); - break; - case WPA_EAPOL_portControl_Auto: - if (sta->eapol_sm) - sta->eapol_sm->portControl = Auto; - break; - case WPA_EAPOL_keyRun: - if (sta->eapol_sm) - sta->eapol_sm->keyRun = value ? TRUE : FALSE; - break; - case WPA_EAPOL_keyAvailable: - if (sta->eapol_sm) - sta->eapol_sm->eap_if->eapKeyAvailable = - value ? TRUE : FALSE; - break; - case WPA_EAPOL_keyDone: - if (sta->eapol_sm) - sta->eapol_sm->keyDone = value ? TRUE : FALSE; - break; - case WPA_EAPOL_inc_EapolFramesTx: - if (sta->eapol_sm) - sta->eapol_sm->dot1xAuthEapolFramesTx++; - break; - } -} - - -static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr, - wpa_eapol_variable var) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta = ap_get_sta(hapd, addr); - if (sta == NULL || sta->eapol_sm == NULL) - return -1; - switch (var) { - case WPA_EAPOL_keyRun: - return sta->eapol_sm->keyRun; - case WPA_EAPOL_keyAvailable: - return sta->eapol_sm->eap_if->eapKeyAvailable; - default: - return -1; - } -} - - -static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, - const u8 *prev_psk) -{ - struct hostapd_data *hapd = ctx; - return hostapd_get_psk(hapd->conf, addr, prev_psk); -} - - -static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk, - size_t *len) -{ - struct hostapd_data *hapd = ctx; - const u8 *key; - size_t keylen; - struct sta_info *sta; - - sta = ap_get_sta(hapd, addr); - if (sta == NULL) - return -1; - - key = ieee802_1x_get_key(sta->eapol_sm, &keylen); - if (key == NULL) - return -1; - - if (keylen > *len) - keylen = *len; - os_memcpy(msk, key, keylen); - *len = keylen; - - return 0; -} - - -static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, const char *alg, - const u8 *addr, int idx, u8 *key, - size_t key_len) -{ - struct hostapd_data *hapd = ctx; - const char *ifname = hapd->conf->iface; - - if (vlan_id > 0) { - ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); - if (ifname == NULL) - return -1; - } - - return hostapd_set_encryption(ifname, hapd, alg, addr, idx, - key, key_len, 1); -} - - -static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx, - u8 *seq) -{ - struct hostapd_data *hapd = ctx; - return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq); -} - - -static int hostapd_wpa_auth_get_seqnum_igtk(void *ctx, const u8 *addr, int idx, - u8 *seq) -{ - struct hostapd_data *hapd = ctx; - return hostapd_get_seqnum_igtk(hapd->conf->iface, hapd, addr, idx, - seq); -} - - -static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr, - const u8 *data, size_t data_len, - int encrypt) -{ - struct hostapd_data *hapd = ctx; - return hostapd_send_eapol(hapd, addr, data, data_len, encrypt); -} - - -static int hostapd_wpa_auth_for_each_sta( - void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx), - void *cb_ctx) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - - for (sta = hapd->sta_list; sta; sta = sta->next) { - if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx)) - return 1; - } - return 0; -} - - -static int hostapd_wpa_auth_for_each_auth( - void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx), - void *cb_ctx) -{ - struct hostapd_data *ohapd; - size_t i, j; - struct hapd_interfaces *interfaces = eloop_get_user_data(); - - for (i = 0; i < interfaces->count; i++) { - for (j = 0; j < interfaces->iface[i]->num_bss; j++) { - ohapd = interfaces->iface[i]->bss[j]; - if (cb(ohapd->wpa_auth, cb_ctx)) - return 1; - } - } - - return 0; -} - - -static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto, - const u8 *data, size_t data_len) -{ - struct hostapd_data *hapd = ctx; - - if (hapd->driver && hapd->driver->send_ether) - return hapd->driver->send_ether(hapd->drv_priv, dst, - hapd->own_addr, proto, - data, data_len); - if (hapd->l2 == NULL) - return -1; - return l2_packet_send(hapd->l2, dst, proto, data, data_len); -} - - -#ifdef CONFIG_IEEE80211R - -static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst, - const u8 *data, size_t data_len) -{ - struct hostapd_data *hapd = ctx; - int res; - struct ieee80211_mgmt *m; - size_t mlen; - struct sta_info *sta; - - sta = ap_get_sta(hapd, dst); - if (sta == NULL || sta->wpa_sm == NULL) - return -1; - - m = os_zalloc(sizeof(*m) + data_len); - if (m == NULL) - return -1; - mlen = ((u8 *) &m->u - (u8 *) m) + data_len; - m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_ACTION); - os_memcpy(m->da, dst, ETH_ALEN); - os_memcpy(m->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); - os_memcpy(&m->u, data, data_len); - - res = hostapd_send_mgmt_frame(hapd, (u8 *) m, mlen, 0); - os_free(m); - return res; -} - - -static struct wpa_state_machine * -hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) -{ - struct hostapd_data *hapd = ctx; - struct sta_info *sta; - - sta = ap_sta_add(hapd, sta_addr); - if (sta == NULL) - return NULL; - if (sta->wpa_sm) - return sta->wpa_sm; - - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr); - if (sta->wpa_sm == NULL) { - ap_free_sta(hapd, sta); - return NULL; - } - sta->auth_alg = WLAN_AUTH_FT; - - return sta->wpa_sm; -} - - -static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, - size_t len) -{ - struct hostapd_data *hapd = ctx; - wpa_ft_rrb_rx(hapd->wpa_auth, src_addr, buf, len); -} - -#endif /* CONFIG_IEEE80211R */ - - -/** - * hostapd_validate_bssid_configuration - Validate BSSID configuration - * @iface: Pointer to interface data - * Returns: 0 on success, -1 on failure - * - * This function is used to validate that the configured BSSIDs are valid. - */ -static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface) -{ - u8 mask[ETH_ALEN] = { 0 }; - struct hostapd_data *hapd = iface->bss[0]; - unsigned int i = iface->conf->num_bss, bits = 0, j; - int res; - - if (hostapd_drv_none(hapd)) - return 0; - - /* Generate BSSID mask that is large enough to cover the BSSIDs. */ - - /* Determine the bits necessary to cover the number of BSSIDs. */ - for (i--; i; i >>= 1) - bits++; - - /* Determine the bits necessary to any configured BSSIDs, - if they are higher than the number of BSSIDs. */ - for (j = 0; j < iface->conf->num_bss; j++) { - if (hostapd_mac_comp_empty(iface->conf->bss[j].bssid) == 0) - continue; - - for (i = 0; i < ETH_ALEN; i++) { - mask[i] |= - iface->conf->bss[j].bssid[i] ^ - hapd->own_addr[i]; - } - } - - for (i = 0; i < ETH_ALEN && mask[i] == 0; i++) - ; - j = 0; - if (i < ETH_ALEN) { - j = (5 - i) * 8; - - while (mask[i] != 0) { - mask[i] >>= 1; - j++; - } - } - - if (bits < j) - bits = j; - - if (bits > 40) - return -1; - - os_memset(mask, 0xff, ETH_ALEN); - j = bits / 8; - for (i = 5; i > 5 - j; i--) - mask[i] = 0; - j = bits % 8; - while (j--) - mask[i] <<= 1; - - wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)", - (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits); - - res = hostapd_valid_bss_mask(hapd, hapd->own_addr, mask); - if (res == 0) - return 0; - - if (res < 0) { - wpa_printf(MSG_ERROR, "Driver did not accept BSSID mask " - MACSTR " for start address " MACSTR ".", - MAC2STR(mask), MAC2STR(hapd->own_addr)); - return -1; - } - - for (i = 0; i < ETH_ALEN; i++) { - if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) { - wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR - " for start address " MACSTR ".", - MAC2STR(mask), MAC2STR(hapd->own_addr)); - wpa_printf(MSG_ERROR, "Start address must be the " - "first address in the block (i.e., addr " - "AND mask == addr)."); - return -1; - } - } - - return 0; -} - - -static int mac_in_conf(struct hostapd_config *conf, const void *a) -{ - size_t i; - - for (i = 0; i < conf->num_bss; i++) { - if (hostapd_mac_comp(conf->bss[i].bssid, a) == 0) { - return 1; - } - } - - return 0; -} - - -static int hostapd_setup_wpa(struct hostapd_data *hapd) -{ - struct wpa_auth_config _conf; - struct wpa_auth_callbacks cb; - const u8 *wpa_ie; - size_t wpa_ie_len; - - hostapd_wpa_auth_conf(hapd->conf, &_conf); - os_memset(&cb, 0, sizeof(cb)); - cb.ctx = hapd; - cb.logger = hostapd_wpa_auth_logger; - cb.disconnect = hostapd_wpa_auth_disconnect; - cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report; - cb.set_eapol = hostapd_wpa_auth_set_eapol; - cb.get_eapol = hostapd_wpa_auth_get_eapol; - cb.get_psk = hostapd_wpa_auth_get_psk; - cb.get_msk = hostapd_wpa_auth_get_msk; - cb.set_key = hostapd_wpa_auth_set_key; - cb.get_seqnum = hostapd_wpa_auth_get_seqnum; - cb.get_seqnum_igtk = hostapd_wpa_auth_get_seqnum_igtk; - cb.send_eapol = hostapd_wpa_auth_send_eapol; - cb.for_each_sta = hostapd_wpa_auth_for_each_sta; - cb.for_each_auth = hostapd_wpa_auth_for_each_auth; - cb.send_ether = hostapd_wpa_auth_send_ether; -#ifdef CONFIG_IEEE80211R - cb.send_ft_action = hostapd_wpa_auth_send_ft_action; - cb.add_sta = hostapd_wpa_auth_add_sta; -#endif /* CONFIG_IEEE80211R */ - hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb); - if (hapd->wpa_auth == NULL) { - wpa_printf(MSG_ERROR, "WPA initialization failed."); - return -1; - } - - if (hostapd_set_privacy(hapd, 1)) { - wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked " - "for interface %s", hapd->conf->iface); - return -1; - } - - wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); - if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) { - wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " - "the kernel driver."); - return -1; - } - - if (rsn_preauth_iface_init(hapd)) { - wpa_printf(MSG_ERROR, "Initialization of RSN " - "pre-authentication failed."); - return -1; - } - - return 0; - -} - - -static int hostapd_setup_radius_srv(struct hostapd_data *hapd, - struct hostapd_bss_config *conf) -{ - struct radius_server_conf srv; - os_memset(&srv, 0, sizeof(srv)); - srv.client_file = conf->radius_server_clients; - srv.auth_port = conf->radius_server_auth_port; - srv.conf_ctx = conf; - srv.eap_sim_db_priv = hapd->eap_sim_db_priv; - srv.ssl_ctx = hapd->ssl_ctx; - srv.pac_opaque_encr_key = conf->pac_opaque_encr_key; - srv.eap_fast_a_id = conf->eap_fast_a_id; - srv.eap_fast_a_id_len = conf->eap_fast_a_id_len; - srv.eap_fast_a_id_info = conf->eap_fast_a_id_info; - srv.eap_fast_prov = conf->eap_fast_prov; - srv.pac_key_lifetime = conf->pac_key_lifetime; - srv.pac_key_refresh_time = conf->pac_key_refresh_time; - srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; - srv.tnc = conf->tnc; - srv.wps = hapd->wps; - srv.ipv6 = conf->radius_server_ipv6; - srv.get_eap_user = hostapd_radius_get_eap_user; - srv.eap_req_id_text = conf->eap_req_id_text; - srv.eap_req_id_text_len = conf->eap_req_id_text_len; - - hapd->radius_srv = radius_server_init(&srv); - if (hapd->radius_srv == NULL) { - wpa_printf(MSG_ERROR, "RADIUS server initialization failed."); - return -1; - } - - return 0; -} - - -/** - * hostapd_setup_bss - Per-BSS setup (initialization) - * @hapd: Pointer to BSS data - * @first: Whether this BSS is the first BSS of an interface - * - * This function is used to initialize all per-BSS data structures and - * resources. This gets called in a loop for each BSS when an interface is - * initialized. Most of the modules that are initialized here will be - * deinitialized in hostapd_cleanup(). - */ -static int hostapd_setup_bss(struct hostapd_data *hapd, int first) -{ - struct hostapd_bss_config *conf = hapd->conf; - u8 ssid[HOSTAPD_MAX_SSID_LEN + 1]; - int ssid_len, set_ssid; - - if (!first) { - if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) { - /* Allocate the next available BSSID. */ - do { - inc_byte_array(hapd->own_addr, ETH_ALEN); - } while (mac_in_conf(hapd->iconf, hapd->own_addr)); - } else { - /* Allocate the configured BSSID. */ - os_memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN); - - if (hostapd_mac_comp(hapd->own_addr, - hapd->iface->bss[0]->own_addr) == - 0) { - wpa_printf(MSG_ERROR, "BSS '%s' may not have " - "BSSID set to the MAC address of " - "the radio", hapd->conf->iface); - return -1; - } - } - - hapd->interface_added = 1; - if (hostapd_bss_add(hapd->iface->bss[0], hapd->conf->iface, - hapd->own_addr)) { - wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID=" - MACSTR ")", MAC2STR(hapd->own_addr)); - return -1; - } - } - - hostapd_flush_old_stations(hapd); - hostapd_set_privacy(hapd, 0); - - hostapd_broadcast_wep_clear(hapd); - if (hostapd_setup_encryption(hapd->conf->iface, hapd)) - return -1; - - /* - * Fetch the SSID from the system and use it or, - * if one was specified in the config file, verify they - * match. - */ - ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid)); - if (ssid_len < 0) { - wpa_printf(MSG_ERROR, "Could not read SSID from system"); - return -1; - } - if (conf->ssid.ssid_set) { - /* - * If SSID is specified in the config file and it differs - * from what is being used then force installation of the - * new SSID. - */ - set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len || - os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0); - } else { - /* - * No SSID in the config file; just use the one we got - * from the system. - */ - set_ssid = 0; - conf->ssid.ssid_len = ssid_len; - os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len); - conf->ssid.ssid[conf->ssid.ssid_len] = '\0'; - } - - if (!hostapd_drv_none(hapd)) { - wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR - " and ssid '%s'", - hapd->conf->iface, MAC2STR(hapd->own_addr), - hapd->conf->ssid.ssid); - } - - if (hostapd_setup_wpa_psk(conf)) { - wpa_printf(MSG_ERROR, "WPA-PSK setup failed."); - return -1; - } - - /* Set flag for whether SSID is broadcast in beacons */ - if (hostapd_set_broadcast_ssid(hapd, - !!hapd->conf->ignore_broadcast_ssid)) { - wpa_printf(MSG_ERROR, "Could not set broadcast SSID flag for " - "kernel driver"); - return -1; - } - - if (hostapd_set_dtim_period(hapd, hapd->conf->dtim_period)) { - wpa_printf(MSG_ERROR, "Could not set DTIM period for kernel " - "driver"); - return -1; - } - - /* Set SSID for the kernel driver (to be used in beacon and probe - * response frames) */ - if (set_ssid && hostapd_set_ssid(hapd, (u8 *) conf->ssid.ssid, - conf->ssid.ssid_len)) { - wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); - return -1; - } - - if (wpa_debug_level == MSG_MSGDUMP) - conf->radius->msg_dumps = 1; - hapd->radius = radius_client_init(hapd, conf->radius); - if (hapd->radius == NULL) { - wpa_printf(MSG_ERROR, "RADIUS client initialization failed."); - return -1; - } - - if (hostapd_acl_init(hapd)) { - wpa_printf(MSG_ERROR, "ACL initialization failed."); - return -1; - } - if (hostapd_init_wps(hapd, conf)) - return -1; - - if (ieee802_1x_init(hapd)) { - wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed."); - return -1; - } - - if (hapd->conf->wpa && hostapd_setup_wpa(hapd)) - return -1; - - if (accounting_init(hapd)) { - wpa_printf(MSG_ERROR, "Accounting initialization failed."); - return -1; - } - - if (hapd->conf->ieee802_11f && - (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) { - wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization " - "failed."); - return -1; - } - - if (hostapd_ctrl_iface_init(hapd)) { - wpa_printf(MSG_ERROR, "Failed to setup control interface"); - return -1; - } - - if (!hostapd_drv_none(hapd) && vlan_init(hapd)) { - wpa_printf(MSG_ERROR, "VLAN initialization failed."); - return -1; - } - -#ifdef CONFIG_IEEE80211R - if (!hostapd_drv_none(hapd)) { - hapd->l2 = l2_packet_init(hapd->conf->iface, NULL, ETH_P_RRB, - hostapd_rrb_receive, hapd, 0); - if (hapd->l2 == NULL && - (hapd->driver == NULL || - hapd->driver->send_ether == NULL)) { - wpa_printf(MSG_ERROR, "Failed to open l2_packet " - "interface"); - return -1; - } - } -#endif /* CONFIG_IEEE80211R */ - - ieee802_11_set_beacon(hapd); - - if (conf->radius_server_clients && - hostapd_setup_radius_srv(hapd, conf)) - return -1; - - return 0; -} - - -static void hostapd_tx_queue_params(struct hostapd_iface *iface) -{ - struct hostapd_data *hapd = iface->bss[0]; - int i; - struct hostapd_tx_queue_params *p; - - for (i = 0; i < NUM_TX_QUEUES; i++) { - p = &iface->conf->tx_queue[i]; - - if (!p->configured) - continue; - - if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin, - p->cwmax, p->burst)) { - wpa_printf(MSG_DEBUG, "Failed to set TX queue " - "parameters for queue %d.", i); - /* Continue anyway */ - } - } -} - - -static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity, - size_t identity_len, int phase2, - struct eap_user *user) -{ - const struct hostapd_eap_user *eap_user; - int i, count; - - eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2); - if (eap_user == NULL) - return -1; - - if (user == NULL) - return 0; - - os_memset(user, 0, sizeof(*user)); - count = EAP_USER_MAX_METHODS; - if (count > EAP_MAX_METHODS) - count = EAP_MAX_METHODS; - for (i = 0; i < count; i++) { - user->methods[i].vendor = eap_user->methods[i].vendor; - user->methods[i].method = eap_user->methods[i].method; - } - - if (eap_user->password) { - user->password = os_malloc(eap_user->password_len); - if (user->password == NULL) - return -1; - os_memcpy(user->password, eap_user->password, - eap_user->password_len); - user->password_len = eap_user->password_len; - user->password_hash = eap_user->password_hash; - } - user->force_version = eap_user->force_version; - user->ttls_auth = eap_user->ttls_auth; - - return 0; -} - - -static int setup_interface(struct hostapd_iface *iface) -{ - struct hostapd_data *hapd = iface->bss[0]; - struct hostapd_bss_config *conf = hapd->conf; - size_t i; - char country[4]; - u8 *b = conf->bssid; - int freq; - size_t j; - u8 *prev_addr; - - /* - * Initialize the driver interface and make sure that all BSSes get - * configured with a pointer to this driver interface. - */ - if (b[0] | b[1] | b[2] | b[3] | b[4] | b[5]) { - hapd->drv_priv = hostapd_driver_init_bssid(hapd, b); - } else { - hapd->drv_priv = hostapd_driver_init(hapd); - } - - if (hapd->drv_priv == NULL) { - wpa_printf(MSG_ERROR, "%s driver initialization failed.", - hapd->driver ? hapd->driver->name : "Unknown"); - hapd->driver = NULL; - return -1; - } - for (i = 0; i < iface->num_bss; i++) { - iface->bss[i]->driver = hapd->driver; - iface->bss[i]->drv_priv = hapd->drv_priv; - } - - if (hostapd_validate_bssid_configuration(iface)) - return -1; - -#ifdef CONFIG_IEEE80211N - SET_2BIT_LE16(&iface->ht_op_mode, - HT_INFO_OPERATION_MODE_OP_MODE_OFFSET, - OP_MODE_PURE); -#endif /* CONFIG_IEEE80211N */ - - if (hapd->iconf->country[0] && hapd->iconf->country[1]) { - os_memcpy(country, hapd->iconf->country, 3); - country[3] = '\0'; - if (hostapd_set_country(hapd, country) < 0) { - wpa_printf(MSG_ERROR, "Failed to set country code"); - return -1; - } - } - - if (hapd->iconf->ieee80211d && - hostapd_set_ieee80211d(hapd, 1) < 0) { - wpa_printf(MSG_ERROR, "Failed to set ieee80211d (%d)", - hapd->iconf->ieee80211d); - return -1; - } - - if (hapd->iconf->bridge_packets != INTERNAL_BRIDGE_DO_NOT_CONTROL && - hostapd_set_internal_bridge(hapd, hapd->iconf->bridge_packets)) { - wpa_printf(MSG_ERROR, "Failed to set bridge_packets for " - "kernel driver"); - return -1; - } - - /* TODO: merge with hostapd_driver_init() ? */ - if (hostapd_wireless_event_init(hapd) < 0) - return -1; - - if (hostapd_get_hw_features(iface)) { - /* Not all drivers support this yet, so continue without hw - * feature data. */ - } else { - int ret = hostapd_select_hw_mode(iface); - if (ret < 0) { - wpa_printf(MSG_ERROR, "Could not select hw_mode and " - "channel. (%d)", ret); - return -1; - } - } - - if (hapd->iconf->channel) { - freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel); - wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d " - "Frequency: %d MHz", - hostapd_hw_mode_txt(hapd->iconf->hw_mode), - hapd->iconf->channel, freq); - - if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, freq, - hapd->iconf->ieee80211n, - hapd->iconf->secondary_channel)) { - wpa_printf(MSG_ERROR, "Could not set channel for " - "kernel driver"); - return -1; - } - } - - hostapd_set_beacon_int(hapd, hapd->iconf->beacon_int); - - if (hapd->iconf->rts_threshold > -1 && - hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) { - wpa_printf(MSG_ERROR, "Could not set RTS threshold for " - "kernel driver"); - return -1; - } - - if (hapd->iconf->fragm_threshold > -1 && - hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) { - wpa_printf(MSG_ERROR, "Could not set fragmentation threshold " - "for kernel driver"); - return -1; - } - - prev_addr = hapd->own_addr; - - for (j = 0; j < iface->num_bss; j++) { - hapd = iface->bss[j]; - if (j) - os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); - if (hostapd_setup_bss(hapd, j == 0)) - return -1; - if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) - prev_addr = hapd->own_addr; - } - - hostapd_tx_queue_params(iface); - - ap_list_init(iface); - - if (hostapd_driver_commit(hapd) < 0) { - wpa_printf(MSG_ERROR, "%s: Failed to commit driver " - "configuration", __func__); - return -1; - } - - return 0; -} - - -/** - * hostapd_setup_interface - Setup of an interface - * @iface: Pointer to interface data. - * Returns: 0 on success, -1 on failure - * - * Initializes the driver interface, validates the configuration, - * and sets driver parameters based on the configuration. - * Flushes old stations, sets the channel, encryption, - * beacons, and WDS links based on the configuration. - */ -static int hostapd_setup_interface(struct hostapd_iface *iface) -{ - int ret; - - ret = setup_interface(iface); - if (ret) { - wpa_printf(MSG_DEBUG, "%s: Unable to setup interface.", - iface->bss[0]->conf->iface); - eloop_terminate(); - return -1; - } else if (!hostapd_drv_none(iface->bss[0])) { - wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", - iface->bss[0]->conf->iface); - } - - return 0; -} - - -static void show_version(void) -{ - fprintf(stderr, - "hostapd v" VERSION_STR "\n" - "User space daemon for IEEE 802.11 AP management,\n" - "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" - "Copyright (c) 2002-2009, Jouni Malinen " - "and contributors\n"); -} - - -static void usage(void) -{ - show_version(); - fprintf(stderr, - "\n" - "usage: hostapd [-hdBKtv] [-P ] " - " \n" - "\n" - "options:\n" - " -h show this usage\n" - " -d show more debug messages (-dd for even more)\n" - " -B run daemon in the background\n" - " -P PID file\n" - " -K include key data in debug messages\n" - " -t include timestamps in some debug messages\n" - " -v show hostapd version\n"); - - exit(1); -} - - -/** - * hostapd_alloc_bss_data - Allocate and initialize per-BSS data - * @hapd_iface: Pointer to interface data - * @conf: Pointer to per-interface configuration - * @bss: Pointer to per-BSS configuration for this BSS - * Returns: Pointer to allocated BSS data - * - * This function is used to allocate per-BSS data structure. This data will be - * freed after hostapd_cleanup() is called for it during interface - * deinitialization. - */ -static struct hostapd_data * -hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, - struct hostapd_config *conf, - struct hostapd_bss_config *bss) -{ - struct hostapd_data *hapd; - - hapd = os_zalloc(sizeof(*hapd)); - if (hapd == NULL) - return NULL; - - hapd->iconf = conf; - hapd->conf = bss; - hapd->iface = hapd_iface; - - if (hapd->conf->individual_wep_key_len > 0) { - /* use key0 in individual key and key1 in broadcast key */ - hapd->default_wep_key_idx = 1; - } - -#ifdef EAP_TLS_FUNCS - if (hapd->conf->eap_server && - (hapd->conf->ca_cert || hapd->conf->server_cert || - hapd->conf->dh_file)) { - struct tls_connection_params params; - - hapd->ssl_ctx = tls_init(NULL); - if (hapd->ssl_ctx == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize TLS"); - goto fail; - } - - os_memset(¶ms, 0, sizeof(params)); - params.ca_cert = hapd->conf->ca_cert; - params.client_cert = hapd->conf->server_cert; - params.private_key = hapd->conf->private_key; - params.private_key_passwd = hapd->conf->private_key_passwd; - params.dh_file = hapd->conf->dh_file; - - if (tls_global_set_params(hapd->ssl_ctx, ¶ms)) { - wpa_printf(MSG_ERROR, "Failed to set TLS parameters"); - goto fail; - } - - if (tls_global_set_verify(hapd->ssl_ctx, - hapd->conf->check_crl)) { - wpa_printf(MSG_ERROR, "Failed to enable check_crl"); - goto fail; - } - } -#endif /* EAP_TLS_FUNCS */ - -#ifdef EAP_SERVER - if (hapd->conf->eap_sim_db) { - hapd->eap_sim_db_priv = - eap_sim_db_init(hapd->conf->eap_sim_db, - hostapd_sim_db_cb, hapd); - if (hapd->eap_sim_db_priv == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM " - "database interface"); - goto fail; - } - } -#endif /* EAP_SERVER */ - - hapd->driver = hapd->iconf->driver; - - return hapd; - -#if defined(EAP_TLS_FUNCS) || defined(EAP_SERVER) -fail: -#endif - /* TODO: cleanup allocated resources(?) */ - os_free(hapd); - return NULL; -} - - -/** - * hostapd_init - Allocate and initialize per-interface data - * @config_file: Path to the configuration file - * Returns: Pointer to the allocated interface data or %NULL on failure - * - * This function is used to allocate main data structures for per-interface - * data. The allocated data buffer will be freed by calling - * hostapd_cleanup_iface(). - */ -static struct hostapd_iface * hostapd_init(const char *config_file) -{ - struct hostapd_iface *hapd_iface = NULL; - struct hostapd_config *conf = NULL; - struct hostapd_data *hapd; - size_t i; - - hapd_iface = os_zalloc(sizeof(*hapd_iface)); - if (hapd_iface == NULL) - goto fail; - - hapd_iface->config_fname = os_strdup(config_file); - if (hapd_iface->config_fname == NULL) - goto fail; - - conf = hostapd_config_read(hapd_iface->config_fname); - if (conf == NULL) - goto fail; - hapd_iface->conf = conf; - - hapd_iface->num_bss = conf->num_bss; - hapd_iface->bss = os_zalloc(conf->num_bss * - sizeof(struct hostapd_data *)); - if (hapd_iface->bss == NULL) - goto fail; - - for (i = 0; i < conf->num_bss; i++) { - hapd = hapd_iface->bss[i] = - hostapd_alloc_bss_data(hapd_iface, conf, - &conf->bss[i]); - if (hapd == NULL) - goto fail; - } - - return hapd_iface; - -fail: - if (conf) - hostapd_config_free(conf); - if (hapd_iface) { - for (i = 0; hapd_iface->bss && i < hapd_iface->num_bss; i++) { - hapd = hapd_iface->bss[i]; - if (hapd && hapd->ssl_ctx) - tls_deinit(hapd->ssl_ctx); - } - - os_free(hapd_iface->config_fname); - os_free(hapd_iface->bss); - os_free(hapd_iface); - } - return NULL; -} - - -int main(int argc, char *argv[]) -{ - struct hapd_interfaces interfaces; - int ret = 1, k; - size_t i, j; - int c, debug = 0, daemonize = 0, tnc = 0; - char *pid_file = NULL; - - hostapd_logger_register_cb(hostapd_logger_cb); - - for (;;) { - c = getopt(argc, argv, "BdhKP:tv"); - 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 '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; - case 'v': - show_version(); - exit(1); - break; - - default: - usage(); - break; - } - } - - if (optind == argc) - usage(); - -#ifdef EAP_SERVER - if (eap_server_register_methods()) { - wpa_printf(MSG_ERROR, "Failed to register EAP methods"); - return -1; - } -#endif /* EAP_SERVER */ - - interfaces.count = argc - optind; - - interfaces.iface = os_malloc(interfaces.count * - sizeof(struct hostapd_iface *)); - if (interfaces.iface == NULL) { - wpa_printf(MSG_ERROR, "malloc failed\n"); - return -1; - } - - if (eloop_init(&interfaces)) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - -#ifndef CONFIG_NATIVE_WINDOWS - eloop_register_signal(SIGHUP, handle_reload, NULL); - eloop_register_signal(SIGUSR1, handle_dump_state, NULL); -#endif /* CONFIG_NATIVE_WINDOWS */ - eloop_register_signal_terminate(handle_term, NULL); - - /* Initialize interfaces */ - for (i = 0; i < interfaces.count; i++) { - wpa_printf(MSG_ERROR, "Configuration file: %s", - argv[optind + i]); - interfaces.iface[i] = hostapd_init(argv[optind + i]); - if (!interfaces.iface[i]) - goto out; - for (k = 0; k < debug; k++) { - if (interfaces.iface[i]->bss[0]->conf-> - logger_stdout_level > 0) - interfaces.iface[i]->bss[0]->conf-> - logger_stdout_level--; - } - - ret = hostapd_setup_interface(interfaces.iface[i]); - if (ret) - goto out; - - for (k = 0; k < (int) interfaces.iface[i]->num_bss; k++) { - if (interfaces.iface[i]->bss[0]->conf->tnc) - tnc++; - } - } - -#ifdef EAP_TNC - if (tnc && tncs_global_init() < 0) { - wpa_printf(MSG_ERROR, "Failed to initialize TNCS"); - goto out; - } -#endif /* EAP_TNC */ - - if (daemonize && os_daemonize(pid_file)) { - perror("daemon"); - goto out; - } - -#ifndef CONFIG_NATIVE_WINDOWS - openlog("hostapd", 0, LOG_DAEMON); -#endif /* CONFIG_NATIVE_WINDOWS */ - - eloop_run(); - - /* Disconnect associated stations from all interfaces and BSSes */ - for (i = 0; i < interfaces.count; i++) { - for (j = 0; j < interfaces.iface[i]->num_bss; j++) { - struct hostapd_data *hapd = - interfaces.iface[i]->bss[j]; - hostapd_free_stas(hapd); - hostapd_flush_old_stations(hapd); - } - } - - ret = 0; - - out: - /* Deinitialize all interfaces */ - for (i = 0; i < interfaces.count; i++) { - if (!interfaces.iface[i]) - continue; - hostapd_cleanup_iface_pre(interfaces.iface[i]); - for (j = 0; j < interfaces.iface[i]->num_bss; j++) { - struct hostapd_data *hapd = - interfaces.iface[i]->bss[j]; - hostapd_cleanup(hapd); - if (j == interfaces.iface[i]->num_bss - 1 && - hapd->driver) - hostapd_driver_deinit(hapd); - } - for (j = 0; j < interfaces.iface[i]->num_bss; j++) - os_free(interfaces.iface[i]->bss[j]); - hostapd_cleanup_iface(interfaces.iface[i]); - } - os_free(interfaces.iface); - -#ifdef EAP_TNC - tncs_global_deinit(); -#endif /* EAP_TNC */ - - eloop_destroy(); - -#ifndef CONFIG_NATIVE_WINDOWS - closelog(); -#endif /* CONFIG_NATIVE_WINDOWS */ - -#ifdef EAP_SERVER - eap_server_unregister_methods(); -#endif /* EAP_SERVER */ - - os_daemonize_terminate(pid_file); - os_free(pid_file); - - return ret; -} diff --git a/contrib/wpa/hostapd/hostapd.conf b/contrib/wpa/hostapd/hostapd.conf index 703b6469b0b8..b44a81868c83 100644 --- a/contrib/wpa/hostapd/hostapd.conf +++ b/contrib/wpa/hostapd/hostapd.conf @@ -5,12 +5,20 @@ # management frames); ath0 for madwifi interface=wlan0 -# In case of madwifi and nl80211 driver interfaces, an additional configuration -# parameter, bridge, must be used to notify hostapd if the interface is -# included in a bridge. This parameter is not used with Host AP driver. +# In case of madwifi, atheros, and nl80211 driver interfaces, an additional +# configuration parameter, bridge, may be used to notify hostapd if the +# interface is included in a bridge. This parameter is not used with Host AP +# driver. If the bridge parameter is not set, the drivers will automatically +# figure out the bridge interface (assuming sysfs is enabled and mounted to +# /sys) and this parameter may not be needed. +# +# For nl80211, this parameter can be used to request the AP interface to be +# added to the bridge automatically (brctl may refuse to do this before hostapd +# has been started to change the interface mode). If needed, the bridge +# interface is also created. #bridge=br0 -# Driver interface type (hostap/wired/madwifi/prism54/test/none/nl80211/bsd); +# Driver interface type (hostap/wired/madwifi/test/none/nl80211/bsd); # default: hostap). nl80211 is used with all Linux mac80211 drivers. # Use driver=none if building hostapd as a standalone RADIUS server that does # not control any wireless/wired driver. @@ -275,6 +283,10 @@ ignore_broadcast_ssid=0 # wmm_enabled=1 # +# WMM-PS Unscheduled Automatic Power Save Delivery [U-APSD] +# Enable this flag if U-APSD supported outside hostapd (eg., Firmware/driver) +#uapsd_advertisement_enabled=1 +# # Low priority / AC_BK = background wmm_ac_bk_cwmin=4 wmm_ac_bk_cwmax=10 @@ -342,34 +354,16 @@ wmm_ac_vo_acm=0 # default: 300 (i.e., 5 minutes) #ap_max_inactivity=300 -# Enable/disable internal bridge for packets between associated stations. -# -# When IEEE 802.11 is used in managed mode, packets are usually send through -# the AP even if they are from a wireless station to another wireless station. -# This functionality requires that the AP has a bridge functionality that sends -# frames back to the same interface if their destination is another associated -# station. In addition, broadcast/multicast frames from wireless stations will -# be sent both to the host system net stack (e.g., to eventually wired network) -# and back to the wireless interface. -# -# The internal bridge is implemented within the wireless kernel module and it -# bypasses kernel filtering (netfilter/iptables/ebtables). If direct -# communication between the stations needs to be prevented, the internal -# bridge can be disabled by setting bridge_packets=0. -# -# Note: If this variable is not included in hostapd.conf, hostapd does not -# change the configuration and iwpriv can be used to set the value with -# 'iwpriv wlan# param 10 0' command. If the variable is in hostapd.conf, -# hostapd will override possible iwpriv configuration whenever configuration -# file is reloaded. -# -# default: do not control from hostapd (80211.o defaults to 1=enabled) -#bridge_packets=1 - # Maximum allowed Listen Interval (how many Beacon periods STAs are allowed to # remain asleep). Default: 65535 (no limit apart from field size) #max_listen_interval=100 +# WDS (4-address frame) mode with per-station virtual interfaces +# (only supported with driver=nl80211) +# This mode allows associated stations to use 4-address frames to allow layer 2 +# bridging to be used. +#wds_sta=1 + ##### IEEE 802.11n related configuration ###################################### # ieee80211n: Whether IEEE 802.11n (HT) is enabled @@ -392,6 +386,10 @@ wmm_ac_vo_acm=0 # 5 GHz 40,48,56,64 36,44,52,60 # (depending on the location, not all of these channels may be available # for use) +# Please note that 40 MHz channels may switch their primary and secondary +# channels if needed or creation of 40 MHz channel maybe rejected based +# on overlapping BSSes. These changes are done automatically when hostapd +# is setting up the 40 MHz channel. # Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC] # (SMPS disabled if neither is set) # HT-greenfield: [GF] (disabled if not set) @@ -522,9 +520,9 @@ eap_server=0 # EAP-FAST authority identity (A-ID) # A-ID indicates the identity of the authority that issues PACs. The A-ID # should be unique across all issuing servers. In theory, this is a variable -# length field, but due to some existing implementations required A-ID to be +# length field, but due to some existing implementations requiring A-ID to be # 16 octets in length, it is strongly recommended to use that length for the -# field to provided interoperability with deployed peer implementation. This +# field to provid interoperability with deployed peer implementations. This # field is configured in hex format. #eap_fast_a_id=101112131415161718191a1b1c1d1e1f @@ -808,7 +806,7 @@ own_ip_addr=127.0.0.1 # And so on.. One line per R0KH. # List of R1KHs in the same Mobility Domain -# format: <128-bit key as hex string> +# format: <128-bit key as hex string> # This list is used to map R1KH-ID to a destination MAC address when sending # PMK-R1 key from the R0KH. This is also the list of authorized R1KHs in the MD # that can request PMK-R1 keys. @@ -821,27 +819,11 @@ own_ip_addr=127.0.0.1 # 1 = push PMK-R1 to all configured R1KHs whenever a new PMK-R0 is derived #pmk_r1_push=1 -##### Passive scanning ######################################################## -# Scan different channels every N seconds. 0 = disable passive scanning. -#passive_scan_interval=60 - -# Listen N usecs on each channel when doing passive scanning. -# This value plus the time needed for changing channels should be less than -# 32 milliseconds (i.e. 32000 usec) to avoid interruptions to normal -# operations. Time needed for channel changing varies based on the used wlan -# hardware. -# default: disabled (0) -#passive_scan_listen=10000 - -# Passive scanning mode: -# 0 = scan all supported modes (802.11a/b/g/Turbo) (default) -# 1 = scan only the mode that is currently used for normal operations -#passive_scan_mode=1 - -# Maximum number of entries kept in AP table (either for passive scanning or -# for detecting Overlapping Legacy BSS Condition). The oldest entry will be +##### Neighbor table ########################################################## +# Maximum number of entries kept in AP table (either for neigbor table or for +# detecting Overlapping Legacy BSS Condition). The oldest entry will be # removed when adding a new entry that would make the list grow over this -# limit. Note! Wi-Fi certification for IEEE 802.11g requires that OLBC is +# limit. Note! WFA certification for IEEE 802.11g requires that OLBC is # enabled, so this field should not be set to 0 when using IEEE 802.11g. # default: 255 #ap_table_max_size=255 @@ -927,11 +909,17 @@ own_ip_addr=127.0.0.1 # Config Methods # List of the supported configuration methods +# Available methods: usba ethernet label display ext_nfc_token int_nfc_token +# nfc_interface push_button keypad #config_methods=label display push_button keypad -# Access point PIN for initial configuration and adding Registrars +# Static access point PIN for initial configuration and adding Registrars # If not set, hostapd will not allow external WPS Registrars to control the -# access point. +# access point. The AP PIN can also be set at runtime with hostapd_cli +# wps_ap_pin command. Use of temporary (enabled by user action) and random +# AP PIN is much more secure than configuring a static AP PIN here. As such, +# use of the ap_pin parameter is not recommended if the AP device has means for +# displaying a random PIN. #ap_pin=12345670 # Skip building of automatic WPS credential @@ -1002,7 +990,10 @@ own_ip_addr=127.0.0.1 # hostapd will generate BSSID mask based on the BSSIDs that are # configured. hostapd will verify that dev_addr & MASK == dev_addr. If this is # not the case, the MAC address of the radio must be changed before starting -# hostapd (ifconfig wlan0 hw ether ). +# hostapd (ifconfig wlan0 hw ether ). If a BSSID is configured for +# every secondary BSS, this limitation is not applied at hostapd and other +# masks may be used if the driver supports them (e.g., swap the locally +# administered bit) # # BSSIDs are assigned in order to each BSS, unless an explicit BSSID is # specified using the 'bssid' parameter. diff --git a/contrib/wpa/hostapd/hostapd.h b/contrib/wpa/hostapd/hostapd.h deleted file mode 100644 index 26f30d7016ff..000000000000 --- a/contrib/wpa/hostapd/hostapd.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * hostapd / Initialization and configuration - * Host AP kernel driver - * Copyright (c) 2002-2008, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef HOSTAPD_H -#define HOSTAPD_H - -#include "common.h" -#include "ap.h" - -#ifndef ETH_ALEN -#define ETH_ALEN 6 -#endif -#ifndef IFNAMSIZ -#define IFNAMSIZ 16 -#endif -#ifndef ETH_P_ALL -#define ETH_P_ALL 0x0003 -#endif -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ -#ifndef ETH_P_EAPOL -#define ETH_P_EAPOL ETH_P_PAE -#endif /* ETH_P_EAPOL */ - -#ifndef ETH_P_RRB -#define ETH_P_RRB 0x890D -#endif /* ETH_P_RRB */ - -#include "config.h" - -#ifdef _MSC_VER -#pragma pack(push, 1) -#endif /* _MSC_VER */ - -#define MAX_VLAN_ID 4094 - -struct ieee8023_hdr { - u8 dest[6]; - u8 src[6]; - u16 ethertype; -} STRUCT_PACKED; - - -struct ieee80211_hdr { - le16 frame_control; - le16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - le16 seq_ctrl; - /* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame - */ -} STRUCT_PACKED; - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -#define IEEE80211_DA_FROMDS addr1 -#define IEEE80211_BSSID_FROMDS addr2 -#define IEEE80211_SA_FROMDS addr3 - -#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr)) - -#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4)) - -/* MTU to be set for the wlan#ap device; this is mainly needed for IEEE 802.1X - * frames that might be longer than normal default MTU and they are not - * fragmented */ -#define HOSTAPD_MTU 2290 - -extern unsigned char rfc1042_header[6]; - -struct hostap_sta_driver_data { - unsigned long rx_packets, tx_packets, rx_bytes, tx_bytes; - unsigned long current_tx_rate; - unsigned long inactive_msec; - unsigned long flags; - unsigned long num_ps_buf_frames; - unsigned long tx_retry_failed; - unsigned long tx_retry_count; - int last_rssi; - int last_ack_rssi; -}; - -struct wpa_driver_ops; -struct wpa_ctrl_dst; -struct radius_server_data; -struct upnp_wps_device_sm; - -#ifdef CONFIG_FULL_DYNAMIC_VLAN -struct full_dynamic_vlan; -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - -/** - * struct hostapd_data - hostapd per-BSS data structure - */ -struct hostapd_data { - struct hostapd_iface *iface; - struct hostapd_config *iconf; - struct hostapd_bss_config *conf; - int interface_added; /* virtual interface added for this BSS */ - - u8 own_addr[ETH_ALEN]; - - int num_sta; /* number of entries in sta_list */ - struct sta_info *sta_list; /* STA info list head */ - struct sta_info *sta_hash[STA_HASH_SIZE]; - - /* pointers to STA info; based on allocated AID or NULL if AID free - * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1 - * and so on - */ - struct sta_info *sta_aid[MAX_AID_TABLE_SIZE]; - - const struct wpa_driver_ops *driver; - void *drv_priv; - - u8 *default_wep_key; - u8 default_wep_key_idx; - - struct radius_client_data *radius; - int radius_client_reconfigured; - u32 acct_session_id_hi, acct_session_id_lo; - - struct iapp_data *iapp; - - struct hostapd_cached_radius_acl *acl_cache; - struct hostapd_acl_query_data *acl_queries; - - struct wpa_authenticator *wpa_auth; - struct eapol_authenticator *eapol_auth; - - struct rsn_preauth_interface *preauth_iface; - time_t michael_mic_failure; - int michael_mic_failures; - int tkip_countermeasures; - - int ctrl_sock; - struct wpa_ctrl_dst *ctrl_dst; - - void *ssl_ctx; - void *eap_sim_db_priv; - struct radius_server_data *radius_srv; - - int parameter_set_count; - -#ifdef CONFIG_FULL_DYNAMIC_VLAN - struct full_dynamic_vlan *full_dynamic_vlan; -#endif /* CONFIG_FULL_DYNAMIC_VLAN */ - - struct l2_packet_data *l2; - struct wps_context *wps; - -#ifdef CONFIG_WPS - u8 *wps_beacon_ie; - size_t wps_beacon_ie_len; - u8 *wps_probe_resp_ie; - size_t wps_probe_resp_ie_len; - unsigned int ap_pin_failures; - struct upnp_wps_device_sm *wps_upnp; -#endif /* CONFIG_WPS */ -}; - - -/** - * struct hostapd_iface - hostapd per-interface data structure - */ -struct hostapd_iface { - char *config_fname; - struct hostapd_config *conf; - - size_t num_bss; - struct hostapd_data **bss; - - int num_ap; /* number of entries in ap_list */ - struct ap_info *ap_list; /* AP info list head */ - struct ap_info *ap_hash[STA_HASH_SIZE]; - struct ap_info *ap_iter_list; - - struct hostapd_hw_modes *hw_features; - int num_hw_features; - struct hostapd_hw_modes *current_mode; - /* Rates that are currently used (i.e., filtered copy of - * current_mode->channels */ - int num_rates; - struct hostapd_rate_data *current_rates; - - u16 hw_flags; - - /* Number of associated Non-ERP stations (i.e., stations using 802.11b - * in 802.11g BSS) */ - int num_sta_non_erp; - - /* Number of associated stations that do not support Short Slot Time */ - int num_sta_no_short_slot_time; - - /* Number of associated stations that do not support Short Preamble */ - int num_sta_no_short_preamble; - - int olbc; /* Overlapping Legacy BSS Condition */ - - /* Number of HT associated stations that do not support greenfield */ - int num_sta_ht_no_gf; - - /* Number of associated non-HT stations */ - int num_sta_no_ht; - - /* Number of HT associated stations 20 MHz */ - int num_sta_ht_20mhz; - - /* Overlapping BSS information */ - int olbc_ht; - -#ifdef CONFIG_IEEE80211N - u16 ht_op_mode; -#endif /* CONFIG_IEEE80211N */ -}; - -void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, - int reassoc); -int hostapd_reload_config(struct hostapd_iface *iface); - -#endif /* HOSTAPD_H */ diff --git a/contrib/wpa/hostapd/hostapd_cli.1 b/contrib/wpa/hostapd/hostapd_cli.1 index 2fe49071a2e3..218ea1588a4a 100644 --- a/contrib/wpa/hostapd/hostapd_cli.1 +++ b/contrib/wpa/hostapd/hostapd_cli.1 @@ -3,7 +3,7 @@ hostapd_cli \- hostapd command-line interface .SH SYNOPSIS .B hostapd_cli -[\-p ] [\-i ] [\-hv] [command..] +[\-p ] [\-i ] [\-a ] [\-hvB] [command..] .SH DESCRIPTION This manual page documents briefly the .B hostapd_cli @@ -38,6 +38,12 @@ Interface to listen on. Default: first interface found in socket path. .TP +.B \-a +Run in daemon mode executing the action file based on events from hostapd. +.TP +.B \-B +Run a daemon in the background. +.TP .B \-h Show usage. .TP diff --git a/contrib/wpa/hostapd/hostapd_cli.c b/contrib/wpa/hostapd/hostapd_cli.c index c2ecd4e23cae..589530e419fc 100644 --- a/contrib/wpa/hostapd/hostapd_cli.c +++ b/contrib/wpa/hostapd/hostapd_cli.c @@ -1,6 +1,6 @@ /* * hostapd - command line interface for hostapd daemon - * Copyright (c) 2004-2009, Jouni Malinen + * Copyright (c) 2004-2010, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -15,14 +15,14 @@ #include "includes.h" #include -#include "wpa_ctrl.h" +#include "common/wpa_ctrl.h" #include "common.h" -#include "version.h" +#include "common/version.h" static const char *hostapd_cli_version = "hostapd_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2009, Jouni Malinen and contributors"; +"Copyright (c) 2004-2010, Jouni Malinen and contributors"; static const char *hostapd_cli_license = @@ -83,12 +83,18 @@ static const char *commands_help = " sta get MIB variables for one station\n" " all_sta get MIB variables for all stations\n" " new_sta add a new station\n" +" deauthenticate deauthenticate a station\n" +" disassociate disassociate a station\n" #ifdef CONFIG_IEEE80211W " sa_query send SA Query to a station\n" #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WPS " wps_pin [timeout] add WPS Enrollee PIN (Device Password)\n" " wps_pbc indicate button pushed to initiate PBC\n" +#ifdef CONFIG_WPS_OOB +" wps_oob use WPS with out-of-band (UFD)\n" +#endif /* CONFIG_WPS_OOB */ +" wps_ap_pin [params..] enable/disable AP PIN\n" #endif /* CONFIG_WPS */ " help show this usage help\n" " interface [ifname] show interfaces/select interface\n" @@ -101,23 +107,29 @@ static int hostapd_cli_quit = 0; static int hostapd_cli_attached = 0; static const char *ctrl_iface_dir = "/var/run/hostapd"; static char *ctrl_ifname = NULL; +static const char *pid_file = NULL; +static const char *action_file = NULL; static int ping_interval = 5; static void usage(void) { fprintf(stderr, "%s\n", hostapd_cli_version); - fprintf(stderr, - "\n" - "usage: hostapd_cli [-p ] [-i ] [-hv] " - "[-G ] \\\n" - " [command..]\n" + fprintf(stderr, + "\n" + "usage: hostapd_cli [-p ] [-i ] [-hvB] " + "[-a ] \\\n" + " [-G ] [command..]\n" "\n" "Options:\n" " -h help (show this usage text)\n" " -v shown version information\n" " -p path to find control sockets (default: " "/var/run/hostapd)\n" + " -a run in daemon mode executing the action file " + "based on events\n" + " from hostapd\n" + " -B run a daemon in the background\n" " -i Interface to listen on (default: first " "interface found in the\n" " socket path)\n\n" @@ -212,6 +224,51 @@ static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) } +static int hostapd_cli_exec(const char *program, const char *arg1, + const char *arg2) +{ + char *cmd; + size_t len; + int res; + int ret = 0; + + len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3; + cmd = os_malloc(len); + if (cmd == NULL) + return -1; + res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2); + if (res < 0 || (size_t) res >= len) { + os_free(cmd); + return -1; + } + cmd[len - 1] = '\0'; +#ifndef _WIN32_WCE + if (system(cmd) < 0) + ret = -1; +#endif /* _WIN32_WCE */ + os_free(cmd); + + return ret; +} + + +static void hostapd_cli_action_process(char *msg, size_t len) +{ + const char *pos; + + pos = msg; + if (*pos == '<') { + pos = os_strchr(pos, '>'); + if (pos) + pos++; + else + pos = msg; + } + + hostapd_cli_exec(action_file, ctrl_ifname, pos); +} + + static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) { char buf[64]; @@ -239,6 +296,42 @@ static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc, } +static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char buf[64]; + if (argc < 1) { + printf("Invalid 'deauthenticate' command - exactly one " + "argument, STA address, is required.\n"); + return -1; + } + if (argc > 1) + os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s", + argv[0], argv[1]); + else + os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]); + return wpa_ctrl_command(ctrl, buf); +} + + +static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char buf[64]; + if (argc < 1) { + printf("Invalid 'disassociate' command - exactly one " + "argument, STA address, is required.\n"); + return -1; + } + if (argc > 1) + os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s", + argv[0], argv[1]); + else + os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]); + return wpa_ctrl_command(ctrl, buf); +} + + #ifdef CONFIG_IEEE80211W static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc, char *argv[]) @@ -279,6 +372,61 @@ static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, { return wpa_ctrl_command(ctrl, "WPS_PBC"); } + + +#ifdef CONFIG_WPS_OOB +static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char cmd[256]; + int res; + + if (argc != 3 && argc != 4) { + printf("Invalid WPS_OOB command: need three or four " + "arguments:\n" + "- DEV_TYPE: use 'ufd' or 'nfc'\n" + "- PATH: path of OOB device like '/mnt'\n" + "- METHOD: OOB method 'pin-e' or 'pin-r', " + "'cred'\n" + "- DEV_NAME: (only for NFC) device name like " + "'pn531'\n"); + return -1; + } + + if (argc == 3) + res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s", + argv[0], argv[1], argv[2]); + else + res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s", + argv[0], argv[1], argv[2], argv[3]); + if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { + printf("Too long WPS_OOB command.\n"); + return -1; + } + return wpa_ctrl_command(ctrl, cmd); +} +#endif /* CONFIG_WPS_OOB */ + + +static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + char buf[64]; + if (argc < 1) { + printf("Invalid 'wps_ap_pin' command - at least one argument " + "is required.\n"); + return -1; + } + if (argc > 2) + snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s", + argv[0], argv[1], argv[2]); + else if (argc > 1) + snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s", + argv[0], argv[1]); + else + snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]); + return wpa_ctrl_command(ctrl, buf); +} #endif /* CONFIG_WPS */ @@ -430,12 +578,18 @@ static struct hostapd_cli_cmd hostapd_cli_commands[] = { { "sta", hostapd_cli_cmd_sta }, { "all_sta", hostapd_cli_cmd_all_sta }, { "new_sta", hostapd_cli_cmd_new_sta }, + { "deauthenticate", hostapd_cli_cmd_deauthenticate }, + { "disassociate", hostapd_cli_cmd_disassociate }, #ifdef CONFIG_IEEE80211W { "sa_query", hostapd_cli_cmd_sa_query }, #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_WPS { "wps_pin", hostapd_cli_cmd_wps_pin }, { "wps_pbc", hostapd_cli_cmd_wps_pbc }, +#ifdef CONFIG_WPS_OOB + { "wps_oob", hostapd_cli_cmd_wps_oob }, +#endif /* CONFIG_WPS_OOB */ + { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin }, #endif /* CONFIG_WPS */ { "help", hostapd_cli_cmd_help }, { "interface", hostapd_cli_cmd_interface }, @@ -480,7 +634,8 @@ static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) } -static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read) +static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read, + int action_monitor) { int first = 1; if (ctrl_conn == NULL) @@ -490,10 +645,14 @@ static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read) size_t len = sizeof(buf) - 1; if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { buf[len] = '\0'; - if (in_read && first) - printf("\n"); - first = 0; - printf("%s\n", buf); + if (action_monitor) + hostapd_cli_action_process(buf, len); + else { + if (in_read && first) + printf("\n"); + first = 0; + printf("%s\n", buf); + } } else { printf("Could not read pending message.\n"); break; @@ -511,7 +670,7 @@ static void hostapd_cli_interactive(void) printf("\nInteractive mode\n\n"); do { - hostapd_cli_recv_pending(ctrl_conn, 0); + hostapd_cli_recv_pending(ctrl_conn, 0, 0); printf("> "); alarm(ping_interval); res = fgets(cmd, sizeof(cmd), stdin); @@ -548,9 +707,19 @@ static void hostapd_cli_interactive(void) } -static void hostapd_cli_terminate(int sig) +static void hostapd_cli_cleanup(void) { hostapd_cli_close_connection(); + if (pid_file) + os_daemonize_terminate(pid_file); + + os_program_deinit(); +} + + +static void hostapd_cli_terminate(int sig) +{ + hostapd_cli_cleanup(); exit(0); } @@ -574,22 +743,69 @@ static void hostapd_cli_alarm(int sig) } } if (ctrl_conn) - hostapd_cli_recv_pending(ctrl_conn, 1); + hostapd_cli_recv_pending(ctrl_conn, 1, 0); alarm(ping_interval); } +static void hostapd_cli_action(struct wpa_ctrl *ctrl) +{ + fd_set rfds; + int fd, res; + struct timeval tv; + char buf[256]; + size_t len; + + fd = wpa_ctrl_get_fd(ctrl); + + while (!hostapd_cli_quit) { + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + tv.tv_sec = ping_interval; + tv.tv_usec = 0; + res = select(fd + 1, &rfds, NULL, NULL, &tv); + if (res < 0 && errno != EINTR) { + perror("select"); + break; + } + + if (FD_ISSET(fd, &rfds)) + hostapd_cli_recv_pending(ctrl, 0, 1); + else { + len = sizeof(buf) - 1; + if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len, + hostapd_cli_action_process) < 0 || + len < 4 || os_memcmp(buf, "PONG", 4) != 0) { + printf("hostapd did not reply to PING " + "command - exiting\n"); + break; + } + } + } +} + + int main(int argc, char *argv[]) { int interactive; int warning_displayed = 0; int c; + int daemonize = 0; + + if (os_program_init()) + return -1; for (;;) { - c = getopt(argc, argv, "hG:i:p:v"); + c = getopt(argc, argv, "a:BhG:i:p:v"); if (c < 0) break; switch (c) { + case 'a': + action_file = optarg; + break; + case 'B': + daemonize = 1; + break; case 'G': ping_interval = atoi(optarg); break; @@ -600,8 +816,8 @@ int main(int argc, char *argv[]) printf("%s\n", hostapd_cli_version); return 0; case 'i': - free(ctrl_ifname); - ctrl_ifname = strdup(optarg); + os_free(ctrl_ifname); + ctrl_ifname = os_strdup(optarg); break; case 'p': ctrl_iface_dir = optarg; @@ -612,7 +828,7 @@ int main(int argc, char *argv[]) } } - interactive = argc == optind; + interactive = (argc == optind) && (action_file == NULL); if (interactive) { printf("%s\n\n%s\n\n", hostapd_cli_version, @@ -625,12 +841,13 @@ int main(int argc, char *argv[]) DIR *dir = opendir(ctrl_iface_dir); if (dir) { while ((dent = readdir(dir))) { - if (strcmp(dent->d_name, ".") == 0 || - strcmp(dent->d_name, "..") == 0) + if (os_strcmp(dent->d_name, ".") == 0 + || + os_strcmp(dent->d_name, "..") == 0) continue; printf("Selected interface '%s'\n", dent->d_name); - ctrl_ifname = strdup(dent->d_name); + ctrl_ifname = os_strdup(dent->d_name); break; } closedir(dir); @@ -653,7 +870,7 @@ int main(int argc, char *argv[]) printf("Could not connect to hostapd - re-trying\n"); warning_displayed = 1; } - sleep(1); + os_sleep(1, 0); continue; } @@ -661,17 +878,27 @@ int main(int argc, char *argv[]) signal(SIGTERM, hostapd_cli_terminate); signal(SIGALRM, hostapd_cli_alarm); - if (interactive) { + if (interactive || action_file) { if (wpa_ctrl_attach(ctrl_conn) == 0) { hostapd_cli_attached = 1; } else { printf("Warning: Failed to attach to hostapd.\n"); + if (action_file) + return -1; } + } + + if (daemonize && os_daemonize(pid_file)) + return -1; + + if (interactive) hostapd_cli_interactive(); - } else + else if (action_file) + hostapd_cli_action(ctrl_conn); + else wpa_request(ctrl_conn, argc - optind, &argv[optind]); - free(ctrl_ifname); - hostapd_cli_close_connection(); + os_free(ctrl_ifname); + hostapd_cli_cleanup(); return 0; } diff --git a/contrib/wpa/hostapd/main.c b/contrib/wpa/hostapd/main.c new file mode 100644 index 000000000000..9c532d4cce6e --- /dev/null +++ b/contrib/wpa/hostapd/main.c @@ -0,0 +1,565 @@ +/* + * hostapd / main() + * Copyright (c) 2002-2010, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "utils/includes.h" +#ifndef CONFIG_NATIVE_WINDOWS +#include +#endif /* CONFIG_NATIVE_WINDOWS */ + +#include "utils/common.h" +#include "utils/eloop.h" +#include "crypto/tls.h" +#include "common/version.h" +#include "drivers/driver.h" +#include "eap_server/eap.h" +#include "eap_server/tncs.h" +#include "ap/hostapd.h" +#include "ap/ap_config.h" +#include "config_file.h" +#include "eap_register.h" +#include "dump_state.h" +#include "ctrl_iface.h" + + +extern int wpa_debug_level; +extern int wpa_debug_show_keys; +extern int wpa_debug_timestamp; + + +struct hapd_interfaces { + size_t count; + struct hostapd_iface **iface; +}; + + +static int hostapd_for_each_interface(struct hapd_interfaces *interfaces, + int (*cb)(struct hostapd_iface *iface, + void *ctx), void *ctx) +{ + size_t i; + int ret; + + for (i = 0; i < interfaces->count; i++) { + ret = cb(interfaces->iface[i], ctx); + if (ret) + return ret; + } + + return 0; +} + + +#ifndef CONFIG_NO_HOSTAPD_LOGGER +static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, + int level, const char *txt, size_t len) +{ + struct hostapd_data *hapd = ctx; + char *format, *module_str; + int maxlen; + int conf_syslog_level, conf_stdout_level; + unsigned int conf_syslog, conf_stdout; + + maxlen = len + 100; + format = os_malloc(maxlen); + if (!format) + return; + + if (hapd && hapd->conf) { + conf_syslog_level = hapd->conf->logger_syslog_level; + conf_stdout_level = hapd->conf->logger_stdout_level; + conf_syslog = hapd->conf->logger_syslog; + conf_stdout = hapd->conf->logger_stdout; + } else { + conf_syslog_level = conf_stdout_level = 0; + conf_syslog = conf_stdout = (unsigned int) -1; + } + + switch (module) { + case HOSTAPD_MODULE_IEEE80211: + module_str = "IEEE 802.11"; + break; + case HOSTAPD_MODULE_IEEE8021X: + module_str = "IEEE 802.1X"; + break; + case HOSTAPD_MODULE_RADIUS: + module_str = "RADIUS"; + break; + case HOSTAPD_MODULE_WPA: + module_str = "WPA"; + break; + case HOSTAPD_MODULE_DRIVER: + module_str = "DRIVER"; + break; + case HOSTAPD_MODULE_IAPP: + module_str = "IAPP"; + break; + case HOSTAPD_MODULE_MLME: + module_str = "MLME"; + break; + default: + module_str = NULL; + break; + } + + if (hapd && hapd->conf && addr) + os_snprintf(format, maxlen, "%s: STA " MACSTR "%s%s: %s", + hapd->conf->iface, MAC2STR(addr), + module_str ? " " : "", module_str, txt); + else if (hapd && hapd->conf) + os_snprintf(format, maxlen, "%s:%s%s %s", + hapd->conf->iface, module_str ? " " : "", + module_str, txt); + else if (addr) + os_snprintf(format, maxlen, "STA " MACSTR "%s%s: %s", + MAC2STR(addr), module_str ? " " : "", + module_str, txt); + else + os_snprintf(format, maxlen, "%s%s%s", + module_str, module_str ? ": " : "", txt); + + if ((conf_stdout & module) && level >= conf_stdout_level) { + wpa_debug_print_timestamp(); + printf("%s\n", format); + } + +#ifndef CONFIG_NATIVE_WINDOWS + if ((conf_syslog & module) && level >= conf_syslog_level) { + int priority; + switch (level) { + case HOSTAPD_LEVEL_DEBUG_VERBOSE: + case HOSTAPD_LEVEL_DEBUG: + priority = LOG_DEBUG; + break; + case HOSTAPD_LEVEL_INFO: + priority = LOG_INFO; + break; + case HOSTAPD_LEVEL_NOTICE: + priority = LOG_NOTICE; + break; + case HOSTAPD_LEVEL_WARNING: + priority = LOG_WARNING; + break; + default: + priority = LOG_INFO; + break; + } + syslog(priority, "%s", format); + } +#endif /* CONFIG_NATIVE_WINDOWS */ + + os_free(format); +} +#endif /* CONFIG_NO_HOSTAPD_LOGGER */ + + +/** + * hostapd_init - Allocate and initialize per-interface data + * @config_file: Path to the configuration file + * Returns: Pointer to the allocated interface data or %NULL on failure + * + * This function is used to allocate main data structures for per-interface + * data. The allocated data buffer will be freed by calling + * hostapd_cleanup_iface(). + */ +static struct hostapd_iface * hostapd_init(const char *config_file) +{ + struct hostapd_iface *hapd_iface = NULL; + struct hostapd_config *conf = NULL; + struct hostapd_data *hapd; + size_t i; + + hapd_iface = os_zalloc(sizeof(*hapd_iface)); + if (hapd_iface == NULL) + goto fail; + + hapd_iface->reload_config = hostapd_reload_config; + hapd_iface->config_read_cb = hostapd_config_read; + hapd_iface->config_fname = os_strdup(config_file); + if (hapd_iface->config_fname == NULL) + goto fail; + hapd_iface->ctrl_iface_init = hostapd_ctrl_iface_init; + hapd_iface->ctrl_iface_deinit = hostapd_ctrl_iface_deinit; + hapd_iface->for_each_interface = hostapd_for_each_interface; + + conf = hostapd_config_read(hapd_iface->config_fname); + if (conf == NULL) + goto fail; + hapd_iface->conf = conf; + + hapd_iface->num_bss = conf->num_bss; + hapd_iface->bss = os_zalloc(conf->num_bss * + sizeof(struct hostapd_data *)); + if (hapd_iface->bss == NULL) + goto fail; + + for (i = 0; i < conf->num_bss; i++) { + hapd = hapd_iface->bss[i] = + hostapd_alloc_bss_data(hapd_iface, conf, + &conf->bss[i]); + if (hapd == NULL) + goto fail; + hapd->msg_ctx = hapd; + } + + return hapd_iface; + +fail: + if (conf) + hostapd_config_free(conf); + if (hapd_iface) { + os_free(hapd_iface->config_fname); + os_free(hapd_iface->bss); + os_free(hapd_iface); + } + return NULL; +} + + +static int hostapd_driver_init(struct hostapd_iface *iface) +{ + struct wpa_init_params params; + size_t i; + struct hostapd_data *hapd = iface->bss[0]; + struct hostapd_bss_config *conf = hapd->conf; + u8 *b = conf->bssid; + + if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) { + wpa_printf(MSG_ERROR, "No hostapd driver wrapper available"); + return -1; + } + + /* Initialize the driver interface */ + if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) + b = NULL; + + os_memset(¶ms, 0, sizeof(params)); + params.bssid = b; + params.ifname = hapd->conf->iface; + params.ssid = (const u8 *) hapd->conf->ssid.ssid; + params.ssid_len = hapd->conf->ssid.ssid_len; + params.test_socket = hapd->conf->test_socket; + params.use_pae_group_addr = hapd->conf->use_pae_group_addr; + + params.num_bridge = hapd->iface->num_bss; + params.bridge = os_zalloc(hapd->iface->num_bss * sizeof(char *)); + if (params.bridge == NULL) + return -1; + for (i = 0; i < hapd->iface->num_bss; i++) { + struct hostapd_data *bss = hapd->iface->bss[i]; + if (bss->conf->bridge[0]) + params.bridge[i] = bss->conf->bridge; + } + + params.own_addr = hapd->own_addr; + + hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms); + os_free(params.bridge); + if (hapd->drv_priv == NULL) { + wpa_printf(MSG_ERROR, "%s driver initialization failed.", + hapd->driver->name); + hapd->driver = NULL; + return -1; + } + + return 0; +} + + +static void hostapd_interface_deinit_free(struct hostapd_iface *iface) +{ + const struct wpa_driver_ops *driver; + void *drv_priv; + if (iface == NULL) + return; + driver = iface->bss[0]->driver; + drv_priv = iface->bss[0]->drv_priv; + hostapd_interface_deinit(iface); + if (driver && driver->hapd_deinit) + driver->hapd_deinit(drv_priv); + hostapd_interface_free(iface); +} + + +static struct hostapd_iface * +hostapd_interface_init(struct hapd_interfaces *interfaces, + const char *config_fname, int debug) +{ + struct hostapd_iface *iface; + int k; + + wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname); + iface = hostapd_init(config_fname); + if (!iface) + return NULL; + iface->interfaces = interfaces; + + for (k = 0; k < debug; k++) { + if (iface->bss[0]->conf->logger_stdout_level > 0) + iface->bss[0]->conf->logger_stdout_level--; + } + + if (hostapd_driver_init(iface) || + hostapd_setup_interface(iface)) { + hostapd_interface_deinit_free(iface); + return NULL; + } + + return iface; +} + + +/** + * handle_term - SIGINT and SIGTERM handler to terminate hostapd process + */ +static void handle_term(int sig, void *signal_ctx) +{ + wpa_printf(MSG_DEBUG, "Signal %d received - terminating", sig); + eloop_terminate(); +} + + +#ifndef CONFIG_NATIVE_WINDOWS + +static int handle_reload_iface(struct hostapd_iface *iface, void *ctx) +{ + if (hostapd_reload_config(iface) < 0) { + wpa_printf(MSG_WARNING, "Failed to read new configuration " + "file - continuing with old."); + } + return 0; +} + + +/** + * handle_reload - SIGHUP handler to reload configuration + */ +static void handle_reload(int sig, void *signal_ctx) +{ + struct hapd_interfaces *interfaces = signal_ctx; + wpa_printf(MSG_DEBUG, "Signal %d received - reloading configuration", + sig); + hostapd_for_each_interface(interfaces, handle_reload_iface, NULL); +} + + +static void handle_dump_state(int sig, void *signal_ctx) +{ +#ifdef HOSTAPD_DUMP_STATE + struct hapd_interfaces *interfaces = signal_ctx; + hostapd_for_each_interface(interfaces, handle_dump_state_iface, NULL); +#endif /* HOSTAPD_DUMP_STATE */ +} +#endif /* CONFIG_NATIVE_WINDOWS */ + + +static int hostapd_global_init(struct hapd_interfaces *interfaces) +{ + hostapd_logger_register_cb(hostapd_logger_cb); + + if (eap_server_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; + } + +#ifndef CONFIG_NATIVE_WINDOWS + eloop_register_signal(SIGHUP, handle_reload, interfaces); + eloop_register_signal(SIGUSR1, handle_dump_state, interfaces); +#endif /* CONFIG_NATIVE_WINDOWS */ + eloop_register_signal_terminate(handle_term, interfaces); + +#ifndef CONFIG_NATIVE_WINDOWS + openlog("hostapd", 0, LOG_DAEMON); +#endif /* CONFIG_NATIVE_WINDOWS */ + + return 0; +} + + +static void hostapd_global_deinit(const char *pid_file) +{ +#ifdef EAP_SERVER_TNC + tncs_global_deinit(); +#endif /* EAP_SERVER_TNC */ + + eloop_destroy(); + +#ifndef CONFIG_NATIVE_WINDOWS + closelog(); +#endif /* CONFIG_NATIVE_WINDOWS */ + + eap_server_unregister_methods(); + + os_daemonize_terminate(pid_file); +} + + +static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize, + const char *pid_file) +{ +#ifdef EAP_SERVER_TNC + int tnc = 0; + size_t i, k; + + for (i = 0; !tnc && i < ifaces->count; i++) { + for (k = 0; k < ifaces->iface[i]->num_bss; k++) { + if (ifaces->iface[i]->bss[0]->conf->tnc) { + tnc++; + break; + } + } + } + + if (tnc && tncs_global_init() < 0) { + wpa_printf(MSG_ERROR, "Failed to initialize TNCS"); + return -1; + } +#endif /* EAP_SERVER_TNC */ + + if (daemonize && os_daemonize(pid_file)) { + perror("daemon"); + return -1; + } + + eloop_run(); + + return 0; +} + + +static void show_version(void) +{ + fprintf(stderr, + "hostapd v" VERSION_STR "\n" + "User space daemon for IEEE 802.11 AP management,\n" + "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" + "Copyright (c) 2002-2010, Jouni Malinen " + "and contributors\n"); +} + + +static void usage(void) +{ + show_version(); + fprintf(stderr, + "\n" + "usage: hostapd [-hdBKtv] [-P ] " + " \n" + "\n" + "options:\n" + " -h show this usage\n" + " -d show more debug messages (-dd for even more)\n" + " -B run daemon in the background\n" + " -P PID file\n" + " -K include key data in debug messages\n" + " -t include timestamps in some debug messages\n" + " -v show hostapd version\n"); + + exit(1); +} + + +int main(int argc, char *argv[]) +{ + struct hapd_interfaces interfaces; + int ret = 1; + size_t i; + int c, debug = 0, daemonize = 0; + char *pid_file = NULL; + + if (os_program_init()) + return -1; + + for (;;) { + c = getopt(argc, argv, "BdhKP:tv"); + 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 '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; + case 'v': + show_version(); + exit(1); + break; + + default: + usage(); + break; + } + } + + if (optind == argc) + usage(); + + interfaces.count = argc - optind; + interfaces.iface = os_malloc(interfaces.count * + sizeof(struct hostapd_iface *)); + if (interfaces.iface == NULL) { + wpa_printf(MSG_ERROR, "malloc failed\n"); + return -1; + } + + if (hostapd_global_init(&interfaces)) + return -1; + + /* Initialize interfaces */ + for (i = 0; i < interfaces.count; i++) { + interfaces.iface[i] = hostapd_interface_init(&interfaces, + argv[optind + i], + debug); + if (!interfaces.iface[i]) + goto out; + } + + if (hostapd_global_run(&interfaces, daemonize, pid_file)) + goto out; + + ret = 0; + + out: + /* Deinitialize all interfaces */ + for (i = 0; i < interfaces.count; i++) + hostapd_interface_deinit_free(interfaces.iface[i]); + os_free(interfaces.iface); + + hostapd_global_deinit(pid_file); + os_free(pid_file); + + os_program_deinit(); + + return ret; +} diff --git a/contrib/wpa/hostapd/nt_password_hash.c b/contrib/wpa/hostapd/nt_password_hash.c index 9df307d54a84..839802a744c5 100644 --- a/contrib/wpa/hostapd/nt_password_hash.c +++ b/contrib/wpa/hostapd/nt_password_hash.c @@ -15,7 +15,7 @@ #include "includes.h" #include "common.h" -#include "ms_funcs.h" +#include "crypto/ms_funcs.h" int main(int argc, char *argv[]) @@ -43,7 +43,8 @@ int main(int argc, char *argv[]) password = buf; } - nt_password_hash((u8 *) password, strlen(password), password_hash); + if (nt_password_hash((u8 *) password, strlen(password), password_hash)) + return -1; for (i = 0; i < sizeof(password_hash); i++) printf("%02x", password_hash[i]); printf("\n"); diff --git a/contrib/wpa/hostapd/radiotap.h b/contrib/wpa/hostapd/radiotap.h deleted file mode 100644 index 508264c4cf33..000000000000 --- a/contrib/wpa/hostapd/radiotap.h +++ /dev/null @@ -1,242 +0,0 @@ -/* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */ -/* $NetBSD: ieee80211_radiotap.h,v 1.11 2005/06/22 06:16:02 dyoung Exp $ */ - -/*- - * Copyright (c) 2003, 2004 David Young. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of David Young may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID - * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - */ - -/* - * Modifications to fit into the linux IEEE 802.11 stack, - * Mike Kershaw (dragorn@kismetwireless.net) - */ - -#ifndef IEEE80211RADIOTAP_H -#define IEEE80211RADIOTAP_H - -#include - -/* Base version of the radiotap packet header data */ -#define PKTHDR_RADIOTAP_VERSION 0 - -/* A generic radio capture format is desirable. There is one for - * Linux, but it is neither rigidly defined (there were not even - * units given for some fields) nor easily extensible. - * - * I suggest the following extensible radio capture format. It is - * based on a bitmap indicating which fields are present. - * - * I am trying to describe precisely what the application programmer - * should expect in the following, and for that reason I tell the - * units and origin of each measurement (where it applies), or else I - * use sufficiently weaselly language ("is a monotonically nondecreasing - * function of...") that I cannot set false expectations for lawyerly - * readers. - */ - -/* The radio capture header precedes the 802.11 header. - * All data in the header is little endian on all platforms. - */ -struct ieee80211_radiotap_header { - uint8_t it_version; /* Version 0. Only increases - * for drastic changes, - * introduction of compatible - * new fields does not count. - */ - uint8_t it_pad; - uint16_t it_len; /* length of the whole - * header in bytes, including - * it_version, it_pad, - * it_len, and data fields. - */ - uint32_t it_present; /* A bitmap telling which - * fields are present. Set bit 31 - * (0x80000000) to extend the - * bitmap by another 32 bits. - * Additional extensions are made - * by setting bit 31. - */ -}; - -/* Name Data type Units - * ---- --------- ----- - * - * IEEE80211_RADIOTAP_TSFT __le64 microseconds - * - * Value in microseconds of the MAC's 64-bit 802.11 Time - * Synchronization Function timer when the first bit of the - * MPDU arrived at the MAC. For received frames, only. - * - * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap - * - * Tx/Rx frequency in MHz, followed by flags (see below). - * - * IEEE80211_RADIOTAP_FHSS uint16_t see below - * - * For frequency-hopping radios, the hop set (first byte) - * and pattern (second byte). - * - * IEEE80211_RADIOTAP_RATE u8 500kb/s - * - * Tx/Rx data rate - * - * IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8 decibels from - * one milliwatt (dBm) - * - * RF signal power at the antenna, decibel difference from - * one milliwatt. - * - * IEEE80211_RADIOTAP_DBM_ANTNOISE s8 decibels from - * one milliwatt (dBm) - * - * RF noise power at the antenna, decibel difference from one - * milliwatt. - * - * IEEE80211_RADIOTAP_DB_ANTSIGNAL u8 decibel (dB) - * - * RF signal power at the antenna, decibel difference from an - * arbitrary, fixed reference. - * - * IEEE80211_RADIOTAP_DB_ANTNOISE u8 decibel (dB) - * - * RF noise power at the antenna, decibel difference from an - * arbitrary, fixed reference point. - * - * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless - * - * Quality of Barker code lock. Unitless. Monotonically - * nondecreasing with "better" lock strength. Called "Signal - * Quality" in datasheets. (Is there a standard way to measure - * this?) - * - * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless - * - * Transmit power expressed as unitless distance from max - * power set at factory calibration. 0 is max power. - * Monotonically nondecreasing with lower power levels. - * - * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB) - * - * Transmit power expressed as decibel distance from max power - * set at factory calibration. 0 is max power. Monotonically - * nondecreasing with lower power levels. - * - * IEEE80211_RADIOTAP_DBM_TX_POWER s8 decibels from - * one milliwatt (dBm) - * - * Transmit power expressed as dBm (decibels from a 1 milliwatt - * reference). This is the absolute power level measured at - * the antenna port. - * - * IEEE80211_RADIOTAP_FLAGS u8 bitmap - * - * Properties of transmitted and received frames. See flags - * defined below. - * - * IEEE80211_RADIOTAP_ANTENNA u8 antenna index - * - * Unitless indication of the Rx/Tx antenna for this packet. - * The first antenna is antenna 0. - * - * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap - * - * Properties of received frames. See flags defined below. - * - * IEEE80211_RADIOTAP_TX_FLAGS uint16_t bitmap - * - * Properties of transmitted frames. See flags defined below. - * - * IEEE80211_RADIOTAP_RTS_RETRIES u8 data - * - * Number of rts retries a transmitted frame used. - * - * IEEE80211_RADIOTAP_DATA_RETRIES u8 data - * - * Number of unicast retries a transmitted frame used. - * - */ -enum ieee80211_radiotap_type { - IEEE80211_RADIOTAP_TSFT = 0, - IEEE80211_RADIOTAP_FLAGS = 1, - IEEE80211_RADIOTAP_RATE = 2, - IEEE80211_RADIOTAP_CHANNEL = 3, - IEEE80211_RADIOTAP_FHSS = 4, - IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, - IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, - IEEE80211_RADIOTAP_LOCK_QUALITY = 7, - IEEE80211_RADIOTAP_TX_ATTENUATION = 8, - IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, - IEEE80211_RADIOTAP_DBM_TX_POWER = 10, - IEEE80211_RADIOTAP_ANTENNA = 11, - IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, - IEEE80211_RADIOTAP_DB_ANTNOISE = 13, - IEEE80211_RADIOTAP_RX_FLAGS = 14, - IEEE80211_RADIOTAP_TX_FLAGS = 15, - IEEE80211_RADIOTAP_RTS_RETRIES = 16, - IEEE80211_RADIOTAP_DATA_RETRIES = 17, - IEEE80211_RADIOTAP_EXT = 31 -}; - -/* Channel flags. */ -#define IEEE80211_CHAN_TURBO 0x0010 /* Turbo channel */ -#define IEEE80211_CHAN_CCK 0x0020 /* CCK channel */ -#define IEEE80211_CHAN_OFDM 0x0040 /* OFDM channel */ -#define IEEE80211_CHAN_2GHZ 0x0080 /* 2 GHz spectrum channel. */ -#define IEEE80211_CHAN_5GHZ 0x0100 /* 5 GHz spectrum channel */ -#define IEEE80211_CHAN_PASSIVE 0x0200 /* Only passive scan allowed */ -#define IEEE80211_CHAN_DYN 0x0400 /* Dynamic CCK-OFDM channel */ -#define IEEE80211_CHAN_GFSK 0x0800 /* GFSK channel (FHSS PHY) */ - -/* For IEEE80211_RADIOTAP_FLAGS */ -#define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received - * during CFP - */ -#define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received - * with short - * preamble - */ -#define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received - * with WEP encryption - */ -#define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received - * with fragmentation - */ -#define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ -#define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between - * 802.11 header and payload - * (to 32-bit boundary) - */ -/* For IEEE80211_RADIOTAP_RX_FLAGS */ -#define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */ - -/* For IEEE80211_RADIOTAP_TX_FLAGS */ -#define IEEE80211_RADIOTAP_F_TX_FAIL 0x0001 /* failed due to excessive - * retries */ -#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */ -#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */ - -#endif /* IEEE80211_RADIOTAP_H */ diff --git a/contrib/wpa/hostapd/sta_info.h b/contrib/wpa/hostapd/sta_info.h deleted file mode 100644 index e83597092381..000000000000 --- a/contrib/wpa/hostapd/sta_info.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * hostapd / Station table - * Copyright (c) 2002-2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef STA_INFO_H -#define STA_INFO_H - -int ap_for_each_sta(struct hostapd_data *hapd, - int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, - void *ctx), - void *ctx); -struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta); -void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta); -void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta); -void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta); -void hostapd_free_stas(struct hostapd_data *hapd); -void ap_handle_timer(void *eloop_ctx, void *timeout_ctx); -void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta, - u32 session_timeout); -void ap_sta_no_session_timeout(struct hostapd_data *hapd, - struct sta_info *sta); -struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr); -void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, - u16 reason); -void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, - u16 reason); -int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, - int old_vlanid); -void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta); -void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta); -int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta); - -#endif /* STA_INFO_H */ diff --git a/contrib/wpa/hostapd/wme.h b/contrib/wpa/hostapd/wme.h deleted file mode 100644 index 9bc48cb84950..000000000000 --- a/contrib/wpa/hostapd/wme.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * hostapd / WMM (Wi-Fi Multimedia) - * Copyright 2002-2003, Instant802 Networks, Inc. - * Copyright 2005-2006, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#ifndef WME_H -#define WME_H - -/* - * WMM Information Element (used in (Re)Association Request frames; may also be - * used in Beacon frames) - */ -struct wmm_information_element { - /* Element ID: 221 (0xdd); Length: 7 */ - /* required fields for WMM version 1 */ - u8 oui[3]; /* 00:50:f2 */ - u8 oui_type; /* 2 */ - u8 oui_subtype; /* 0 */ - u8 version; /* 1 for WMM version 1.0 */ - u8 qos_info; /* AP/STA specific QoS info */ -}; - -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) -#include -#include -#endif /* defined(__FreeBSD__) || defined(__NetBSD__) || - * defined(__DragonFly__) */ - - -static inline u16 tsinfo(int tag1d, int contention_based, int direction) -{ - return (tag1d << 11) | (contention_based << 7) | (direction << 5) | - (tag1d << 1); -} - - -struct wme_information_element { - /* required fields for WME version 1 */ - u8 oui[3]; - u8 oui_type; - u8 oui_subtype; - u8 version; - u8 acInfo; - -} __attribute__ ((packed)); - -#define WMM_AC_AIFSN_MASK 0x0f -#define WMM_AC_AIFNS_SHIFT 0 -#define WMM_AC_ACM 0x10 -#define WMM_AC_ACI_MASK 0x60 -#define WMM_AC_ACI_SHIFT 5 - -#define WMM_AC_ECWMIN_MASK 0x0f -#define WMM_AC_ECWMIN_SHIFT 0 -#define WMM_AC_ECWMAX_MASK 0xf0 -#define WMM_AC_ECWMAX_SHIFT 4 - -struct wmm_ac_parameter { - u8 aci_aifsn; /* AIFSN, ACM, ACI */ - u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */ - le16 txop_limit; -} __attribute__ ((packed)); - -/* - * WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association - * Response frmaes) - */ -struct wmm_parameter_element { - /* Element ID: 221 (0xdd); Length: 24 */ - /* required fields for WMM version 1 */ - u8 oui[3]; /* 00:50:f2 */ - u8 oui_type; /* 2 */ - u8 oui_subtype; /* 1 */ - u8 version; /* 1 for WMM version 1.0 */ - u8 qos_info; /* AP/STA specif QoS info */ - u8 reserved; /* 0 */ - struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */ - -} __attribute__ ((packed)); - -/* WMM TSPEC Element */ -struct wmm_tspec_element { - u8 eid; /* 221 = 0xdd */ - u8 length; /* 6 + 55 = 61 */ - u8 oui[3]; /* 00:50:f2 */ - u8 oui_type; /* 2 */ - u8 oui_subtype; /* 2 */ - u8 version; /* 1 */ - /* WMM TSPEC body (55 octets): */ - u8 ts_info[3]; - le16 nominal_msdu_size; - le16 maximum_msdu_size; - le32 minimum_service_interval; - le32 maximum_service_interval; - le32 inactivity_interval; - le32 suspension_interval; - le32 service_start_time; - le32 minimum_data_rate; - le32 mean_data_rate; - le32 peak_data_rate; - le32 maximum_burst_size; - le32 delay_bound; - le32 minimum_phy_rate; - le16 surplus_bandwidth_allowance; - le16 medium_time; -} __attribute__ ((packed)); - - -/* Access Categories / ACI to AC coding */ -enum { - WMM_AC_BE = 0 /* Best Effort */, - WMM_AC_BK = 1 /* Background */, - WMM_AC_VI = 2 /* Video */, - WMM_AC_VO = 3 /* Voice */ -}; - -struct ieee80211_mgmt; - -u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid); -int hostapd_eid_wmm_valid(struct hostapd_data *hapd, u8 *eid, size_t len); -int hostapd_wmm_sta_config(struct hostapd_data *hapd, struct sta_info *sta); -void hostapd_wmm_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len); - -#endif /* WME_H */ diff --git a/contrib/wpa/patches/openssl-0.9.8-tls-extensions.patch b/contrib/wpa/patches/openssl-0.9.8-tls-extensions.patch new file mode 100644 index 000000000000..44490cca226e --- /dev/null +++ b/contrib/wpa/patches/openssl-0.9.8-tls-extensions.patch @@ -0,0 +1,429 @@ +This patch is adding support for TLS hello extensions and externally +generated pre-shared key material to OpenSSL 0.9.8. This is +based on the patch from Alexey Kobozev +(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). + + + +diff -uprN openssl-0.9.8.orig/include/openssl/ssl.h openssl-0.9.8/include/openssl/ssl.h +--- openssl-0.9.8.orig/include/openssl/ssl.h 2005-06-10 12:51:16.000000000 -0700 ++++ openssl-0.9.8/include/openssl/ssl.h 2005-07-19 20:02:15.000000000 -0700 +@@ -340,6 +340,7 @@ extern "C" { + * 'struct ssl_st *' function parameters used to prototype callbacks + * in SSL_CTX. */ + typedef struct ssl_st *ssl_crock_st; ++typedef struct tls_extension_st TLS_EXTENSION; + + /* used to hold info on the particular ciphers used */ + typedef struct ssl_cipher_st +@@ -361,6 +362,8 @@ DECLARE_STACK_OF(SSL_CIPHER) + typedef struct ssl_st SSL; + typedef struct ssl_ctx_st SSL_CTX; + ++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); ++ + /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ + typedef struct ssl_method_st + { +@@ -968,6 +971,15 @@ struct ssl_st + int first_packet; + int client_version; /* what was passed, used for + * SSLv3/TLS rollback check */ ++ ++ /* TLS externsions */ ++ TLS_EXTENSION *tls_extension; ++ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); ++ void *tls_extension_cb_arg; ++ ++ /* TLS pre-shared secret session resumption */ ++ tls_session_secret_cb_fn tls_session_secret_cb; ++ void *tls_session_secret_cb_arg; + }; + + #ifdef __cplusplus +@@ -1533,6 +1545,13 @@ void *SSL_COMP_get_compression_methods(v + int SSL_COMP_add_compression_method(int id,void *cm); + #endif + ++/* TLS extensions functions */ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); ++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); ++ ++/* Pre-shared secret session resumption functions */ ++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); ++ + /* BEGIN ERROR CODES */ + /* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. +@@ -1714,6 +1733,7 @@ void ERR_load_SSL_strings(void); + #define SSL_F_TLS1_ENC 210 + #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 + #define SSL_F_WRITE_PENDING 212 ++#define SSL_F_SSL_SET_HELLO_EXTENSION 213 + + /* Reason codes. */ + #define SSL_R_APP_DATA_IN_HANDSHAKE 100 +diff -uprN openssl-0.9.8.orig/include/openssl/tls1.h openssl-0.9.8/include/openssl/tls1.h +--- openssl-0.9.8.orig/include/openssl/tls1.h 2003-07-22 05:34:21.000000000 -0700 ++++ openssl-0.9.8/include/openssl/tls1.h 2005-07-19 20:02:15.000000000 -0700 +@@ -282,6 +282,14 @@ extern "C" { + #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ + #endif + ++/* TLS extension struct */ ++struct tls_extension_st ++{ ++ unsigned short type; ++ unsigned short length; ++ void *data; ++}; ++ + #ifdef __cplusplus + } + #endif +diff -uprN openssl-0.9.8.orig/ssl/Makefile openssl-0.9.8/ssl/Makefile +--- openssl-0.9.8.orig/ssl/Makefile 2005-05-30 16:20:30.000000000 -0700 ++++ openssl-0.9.8/ssl/Makefile 2005-07-19 20:02:15.000000000 -0700 +@@ -24,7 +24,7 @@ LIBSRC= \ + s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \ + s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \ + s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \ +- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \ ++ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \ + d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ + d1_both.c d1_enc.c \ + ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \ +@@ -35,7 +35,7 @@ LIBOBJ= \ + s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \ + s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \ + s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \ +- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \ ++ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \ + d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \ + d1_both.o d1_enc.o \ + ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \ +@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h .. + t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h + t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h + t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c ++t1_ext.o: t1_ext.c ssl_locl.h +diff -uprN openssl-0.9.8.orig/ssl/s3_clnt.c openssl-0.9.8/ssl/s3_clnt.c +--- openssl-0.9.8.orig/ssl/s3_clnt.c 2005-05-16 03:11:03.000000000 -0700 ++++ openssl-0.9.8/ssl/s3_clnt.c 2005-07-19 20:02:15.000000000 -0700 +@@ -606,6 +606,20 @@ int ssl3_client_hello(SSL *s) + } + *(p++)=0; /* Add the NULL method */ + ++ /* send client hello extensions if any */ ++ if (s->version >= TLS1_VERSION && s->tls_extension) ++ { ++ // set the total extensions length ++ s2n(s->tls_extension->length + 4, p); ++ ++ // put the extensions with type and length ++ s2n(s->tls_extension->type, p); ++ s2n(s->tls_extension->length, p); ++ ++ memcpy(p, s->tls_extension->data, s->tls_extension->length); ++ p+=s->tls_extension->length; ++ } ++ + l=(p-d); + d=buf; + *(d++)=SSL3_MT_CLIENT_HELLO; +@@ -628,7 +642,7 @@ int ssl3_get_server_hello(SSL *s) + STACK_OF(SSL_CIPHER) *sk; + SSL_CIPHER *c; + unsigned char *p,*d; +- int i,al,ok; ++ int i,al,ok,pre_shared; + unsigned int j; + long n; + SSL_COMP *comp; +@@ -693,7 +707,24 @@ int ssl3_get_server_hello(SSL *s) + goto f_err; + } + +- if (j != 0 && j == s->session->session_id_length ++ /* check if we want to resume the session based on external pre-shared secret */ ++ pre_shared = 0; ++ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, ++ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) ++ { ++ s->hit=1; ++ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); ++ s->session->session_id_length = j; ++ memcpy(s->session->session_id, p, j); ++ pre_shared = 1; ++ } ++ } ++ ++ if ((pre_shared || j != 0) && j == s->session->session_id_length + && memcmp(p,s->session->session_id,j) == 0) + { + if(s->sid_ctx_length != s->session->sid_ctx_length +diff -uprN openssl-0.9.8.orig/ssl/s3_srvr.c openssl-0.9.8/ssl/s3_srvr.c +--- openssl-0.9.8.orig/ssl/s3_srvr.c 2005-05-22 17:32:55.000000000 -0700 ++++ openssl-0.9.8/ssl/s3_srvr.c 2005-07-19 20:02:15.000000000 -0700 +@@ -955,6 +955,75 @@ int ssl3_get_client_hello(SSL *s) + } + #endif + ++ /* Check for TLS client hello extension here */ ++ if (p < (d+n) && s->version >= TLS1_VERSION) ++ { ++ if (s->tls_extension_cb) ++ { ++ TLS_EXTENSION tls_ext; ++ unsigned short ext_total_len; ++ ++ n2s(p, ext_total_len); ++ n2s(p, tls_ext.type); ++ n2s(p, tls_ext.length); ++ ++ // sanity check in TLS extension len ++ if (tls_ext.length > (d+n) - p) ++ { ++ // just cut the lenth to packet border ++ tls_ext.length = (d+n) - p; ++ } ++ ++ tls_ext.data = p; ++ ++ // returns an alert code or 0 ++ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg); ++ if (al != 0) ++ { ++ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR); ++ goto f_err; ++ } ++ } ++ } ++ ++ /* Check if we want to use external pre-shared secret for this handshake */ ++ /* for not reused session only */ ++ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, ++ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) ++ { ++ s->hit=1; ++ s->session->ciphers=ciphers; ++ s->session->verify_result=X509_V_OK; ++ ++ ciphers=NULL; ++ ++ /* check if some cipher was preferred by call back */ ++ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); ++ if (pref_cipher == NULL) ++ { ++ al=SSL_AD_HANDSHAKE_FAILURE; ++ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); ++ goto f_err; ++ } ++ ++ s->session->cipher=pref_cipher; ++ ++ if (s->cipher_list) ++ sk_SSL_CIPHER_free(s->cipher_list); ++ ++ if (s->cipher_list_by_id) ++ sk_SSL_CIPHER_free(s->cipher_list_by_id); ++ ++ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); ++ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); ++ } ++ } ++ + /* Given s->session->ciphers and SSL_get_ciphers, we must + * pick a cipher */ + +diff -uprN openssl-0.9.8.orig/ssl/ssl_err.c openssl-0.9.8/ssl/ssl_err.c +--- openssl-0.9.8.orig/ssl/ssl_err.c 2005-06-10 12:51:16.000000000 -0700 ++++ openssl-0.9.8/ssl/ssl_err.c 2005-07-19 20:02:15.000000000 -0700 +@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]= + {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, + {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, + {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, ++{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, + {0,NULL} + }; + +diff -uprN openssl-0.9.8.orig/ssl/ssl.h openssl-0.9.8/ssl/ssl.h +--- openssl-0.9.8.orig/ssl/ssl.h 2005-06-10 12:51:16.000000000 -0700 ++++ openssl-0.9.8/ssl/ssl.h 2005-07-19 20:02:15.000000000 -0700 +@@ -340,6 +340,7 @@ extern "C" { + * 'struct ssl_st *' function parameters used to prototype callbacks + * in SSL_CTX. */ + typedef struct ssl_st *ssl_crock_st; ++typedef struct tls_extension_st TLS_EXTENSION; + + /* used to hold info on the particular ciphers used */ + typedef struct ssl_cipher_st +@@ -361,6 +362,8 @@ DECLARE_STACK_OF(SSL_CIPHER) + typedef struct ssl_st SSL; + typedef struct ssl_ctx_st SSL_CTX; + ++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); ++ + /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ + typedef struct ssl_method_st + { +@@ -968,6 +971,15 @@ struct ssl_st + int first_packet; + int client_version; /* what was passed, used for + * SSLv3/TLS rollback check */ ++ ++ /* TLS externsions */ ++ TLS_EXTENSION *tls_extension; ++ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); ++ void *tls_extension_cb_arg; ++ ++ /* TLS pre-shared secret session resumption */ ++ tls_session_secret_cb_fn tls_session_secret_cb; ++ void *tls_session_secret_cb_arg; + }; + + #ifdef __cplusplus +@@ -1533,6 +1545,13 @@ void *SSL_COMP_get_compression_methods(v + int SSL_COMP_add_compression_method(int id,void *cm); + #endif + ++/* TLS extensions functions */ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); ++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); ++ ++/* Pre-shared secret session resumption functions */ ++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); ++ + /* BEGIN ERROR CODES */ + /* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. +@@ -1714,6 +1733,7 @@ void ERR_load_SSL_strings(void); + #define SSL_F_TLS1_ENC 210 + #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 + #define SSL_F_WRITE_PENDING 212 ++#define SSL_F_SSL_SET_HELLO_EXTENSION 213 + + /* Reason codes. */ + #define SSL_R_APP_DATA_IN_HANDSHAKE 100 +diff -uprN openssl-0.9.8.orig/ssl/ssl_sess.c openssl-0.9.8/ssl/ssl_sess.c +--- openssl-0.9.8.orig/ssl/ssl_sess.c 2005-04-29 13:10:06.000000000 -0700 ++++ openssl-0.9.8/ssl/ssl_sess.c 2005-07-19 20:02:15.000000000 -0700 +@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX * + return(s->session_timeout); + } + ++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, ++ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) ++{ ++ if (s == NULL) return(0); ++ s->tls_session_secret_cb = tls_session_secret_cb; ++ s->tls_session_secret_cb_arg = arg; ++ return(1); ++} ++ + typedef struct timeout_param_st + { + SSL_CTX *ctx; +diff -uprN openssl-0.9.8.orig/ssl/t1_ext.c openssl-0.9.8/ssl/t1_ext.c +--- openssl-0.9.8.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800 ++++ openssl-0.9.8/ssl/t1_ext.c 2005-07-19 20:03:29.000000000 -0700 +@@ -0,0 +1,48 @@ ++ ++#include ++#include "ssl_locl.h" ++ ++ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) ++{ ++ if(s->version >= TLS1_VERSION) ++ { ++ if(s->tls_extension) ++ { ++ OPENSSL_free(s->tls_extension); ++ s->tls_extension = NULL; ++ } ++ ++ if(ext_data) ++ { ++ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); ++ if(!s->tls_extension) ++ { ++ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ ++ s->tls_extension->type = ext_type; ++ s->tls_extension->length = ext_len; ++ s->tls_extension->data = s->tls_extension + 1; ++ memcpy(s->tls_extension->data, ext_data, ext_len); ++ } ++ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg) ++{ ++ if(s->version >= TLS1_VERSION) ++ { ++ s->tls_extension_cb = cb; ++ s->tls_extension_cb_arg = arg; ++ ++ return 1; ++ } ++ ++ return 0; ++} +diff -uprN openssl-0.9.8.orig/ssl/t1_lib.c openssl-0.9.8/ssl/t1_lib.c +--- openssl-0.9.8.orig/ssl/t1_lib.c 2005-04-26 09:02:40.000000000 -0700 ++++ openssl-0.9.8/ssl/t1_lib.c 2005-07-19 20:02:15.000000000 -0700 +@@ -131,6 +131,10 @@ int tls1_new(SSL *s) + + void tls1_free(SSL *s) + { ++ if(s->tls_extension) ++ { ++ OPENSSL_free(s->tls_extension); ++ } + ssl3_free(s); + } + +diff -uprN openssl-0.9.8.orig/ssl/tls1.h openssl-0.9.8/ssl/tls1.h +--- openssl-0.9.8.orig/ssl/tls1.h 2003-07-22 05:34:21.000000000 -0700 ++++ openssl-0.9.8/ssl/tls1.h 2005-07-19 20:02:15.000000000 -0700 +@@ -282,6 +282,14 @@ extern "C" { + #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ + #endif + ++/* TLS extension struct */ ++struct tls_extension_st ++{ ++ unsigned short type; ++ unsigned short length; ++ void *data; ++}; ++ + #ifdef __cplusplus + } + #endif +diff -uprN openssl-0.9.8.orig/util/ssleay.num openssl-0.9.8/util/ssleay.num +--- openssl-0.9.8.orig/util/ssleay.num 2005-05-08 17:22:02.000000000 -0700 ++++ openssl-0.9.8/util/ssleay.num 2005-07-19 20:02:15.000000000 -0700 +@@ -226,3 +226,6 @@ DTLSv1_server_method + SSL_COMP_get_compression_methods 276 EXIST:!VMS:FUNCTION:COMP + SSL_COMP_get_compress_methods 276 EXIST:VMS:FUNCTION:COMP + SSL_SESSION_get_id 277 EXIST::FUNCTION: ++SSL_set_hello_extension 278 EXIST::FUNCTION: ++SSL_set_hello_extension_cb 279 EXIST::FUNCTION: ++SSL_set_session_secret_cb 280 EXIST::FUNCTION: diff --git a/contrib/wpa/patches/openssl-0.9.8d-tls-extensions.patch b/contrib/wpa/patches/openssl-0.9.8d-tls-extensions.patch new file mode 100644 index 000000000000..eec6db8a1341 --- /dev/null +++ b/contrib/wpa/patches/openssl-0.9.8d-tls-extensions.patch @@ -0,0 +1,429 @@ +This patch is adding support for TLS hello extensions and externally +generated pre-shared key material to OpenSSL 0.9.8d. This is +based on the patch from Alexey Kobozev +(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). + + + +diff -uprN openssl-0.9.8d.orig/include/openssl/ssl.h openssl-0.9.8d/include/openssl/ssl.h +--- openssl-0.9.8d.orig/include/openssl/ssl.h 2006-06-14 06:52:49.000000000 -0700 ++++ openssl-0.9.8d/include/openssl/ssl.h 2006-12-10 08:20:02.000000000 -0800 +@@ -345,6 +345,7 @@ extern "C" { + * 'struct ssl_st *' function parameters used to prototype callbacks + * in SSL_CTX. */ + typedef struct ssl_st *ssl_crock_st; ++typedef struct tls_extension_st TLS_EXTENSION; + + /* used to hold info on the particular ciphers used */ + typedef struct ssl_cipher_st +@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER) + typedef struct ssl_st SSL; + typedef struct ssl_ctx_st SSL_CTX; + ++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); ++ + /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ + typedef struct ssl_method_st + { +@@ -973,6 +976,15 @@ struct ssl_st + int first_packet; + int client_version; /* what was passed, used for + * SSLv3/TLS rollback check */ ++ ++ /* TLS externsions */ ++ TLS_EXTENSION *tls_extension; ++ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); ++ void *tls_extension_cb_arg; ++ ++ /* TLS pre-shared secret session resumption */ ++ tls_session_secret_cb_fn tls_session_secret_cb; ++ void *tls_session_secret_cb_arg; + }; + + #ifdef __cplusplus +@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v + int SSL_COMP_add_compression_method(int id,void *cm); + #endif + ++/* TLS extensions functions */ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); ++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); ++ ++/* Pre-shared secret session resumption functions */ ++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); ++ + /* BEGIN ERROR CODES */ + /* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. +@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void); + #define SSL_F_TLS1_ENC 210 + #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 + #define SSL_F_WRITE_PENDING 212 ++#define SSL_F_SSL_SET_HELLO_EXTENSION 213 + + /* Reason codes. */ + #define SSL_R_APP_DATA_IN_HANDSHAKE 100 +diff -uprN openssl-0.9.8d.orig/include/openssl/tls1.h openssl-0.9.8d/include/openssl/tls1.h +--- openssl-0.9.8d.orig/include/openssl/tls1.h 2006-06-14 10:52:01.000000000 -0700 ++++ openssl-0.9.8d/include/openssl/tls1.h 2006-12-10 08:20:02.000000000 -0800 +@@ -296,6 +296,14 @@ extern "C" { + #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ + #endif + ++/* TLS extension struct */ ++struct tls_extension_st ++{ ++ unsigned short type; ++ unsigned short length; ++ void *data; ++}; ++ + #ifdef __cplusplus + } + #endif +diff -uprN openssl-0.9.8d.orig/ssl/Makefile openssl-0.9.8d/ssl/Makefile +--- openssl-0.9.8d.orig/ssl/Makefile 2006-02-03 17:49:35.000000000 -0800 ++++ openssl-0.9.8d/ssl/Makefile 2006-12-10 08:20:02.000000000 -0800 +@@ -24,7 +24,7 @@ LIBSRC= \ + s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \ + s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \ + s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \ +- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \ ++ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \ + d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ + d1_both.c d1_enc.c \ + ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \ +@@ -35,7 +35,7 @@ LIBOBJ= \ + s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \ + s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \ + s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \ +- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \ ++ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \ + d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \ + d1_both.o d1_enc.o \ + ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \ +@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h .. + t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h + t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h + t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c ++t1_ext.o: t1_ext.c ssl_locl.h +diff -uprN openssl-0.9.8d.orig/ssl/s3_clnt.c openssl-0.9.8d/ssl/s3_clnt.c +--- openssl-0.9.8d.orig/ssl/s3_clnt.c 2005-12-12 23:41:46.000000000 -0800 ++++ openssl-0.9.8d/ssl/s3_clnt.c 2006-12-10 08:20:02.000000000 -0800 +@@ -601,6 +601,20 @@ int ssl3_client_hello(SSL *s) + #endif + *(p++)=0; /* Add the NULL method */ + ++ /* send client hello extensions if any */ ++ if (s->version >= TLS1_VERSION && s->tls_extension) ++ { ++ // set the total extensions length ++ s2n(s->tls_extension->length + 4, p); ++ ++ // put the extensions with type and length ++ s2n(s->tls_extension->type, p); ++ s2n(s->tls_extension->length, p); ++ ++ memcpy(p, s->tls_extension->data, s->tls_extension->length); ++ p+=s->tls_extension->length; ++ } ++ + l=(p-d); + d=buf; + *(d++)=SSL3_MT_CLIENT_HELLO; +@@ -623,7 +637,7 @@ int ssl3_get_server_hello(SSL *s) + STACK_OF(SSL_CIPHER) *sk; + SSL_CIPHER *c; + unsigned char *p,*d; +- int i,al,ok; ++ int i,al,ok,pre_shared; + unsigned int j; + long n; + #ifndef OPENSSL_NO_COMP +@@ -690,7 +704,24 @@ int ssl3_get_server_hello(SSL *s) + goto f_err; + } + +- if (j != 0 && j == s->session->session_id_length ++ /* check if we want to resume the session based on external pre-shared secret */ ++ pre_shared = 0; ++ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, ++ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) ++ { ++ s->hit=1; ++ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); ++ s->session->session_id_length = j; ++ memcpy(s->session->session_id, p, j); ++ pre_shared = 1; ++ } ++ } ++ ++ if ((pre_shared || j != 0) && j == s->session->session_id_length + && memcmp(p,s->session->session_id,j) == 0) + { + if(s->sid_ctx_length != s->session->sid_ctx_length +diff -uprN openssl-0.9.8d.orig/ssl/s3_srvr.c openssl-0.9.8d/ssl/s3_srvr.c +--- openssl-0.9.8d.orig/ssl/s3_srvr.c 2006-09-28 04:29:03.000000000 -0700 ++++ openssl-0.9.8d/ssl/s3_srvr.c 2006-12-10 08:20:02.000000000 -0800 +@@ -943,6 +943,75 @@ int ssl3_get_client_hello(SSL *s) + } + #endif + ++ /* Check for TLS client hello extension here */ ++ if (p < (d+n) && s->version >= TLS1_VERSION) ++ { ++ if (s->tls_extension_cb) ++ { ++ TLS_EXTENSION tls_ext; ++ unsigned short ext_total_len; ++ ++ n2s(p, ext_total_len); ++ n2s(p, tls_ext.type); ++ n2s(p, tls_ext.length); ++ ++ // sanity check in TLS extension len ++ if (tls_ext.length > (d+n) - p) ++ { ++ // just cut the lenth to packet border ++ tls_ext.length = (d+n) - p; ++ } ++ ++ tls_ext.data = p; ++ ++ // returns an alert code or 0 ++ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg); ++ if (al != 0) ++ { ++ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR); ++ goto f_err; ++ } ++ } ++ } ++ ++ /* Check if we want to use external pre-shared secret for this handshake */ ++ /* for not reused session only */ ++ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, ++ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) ++ { ++ s->hit=1; ++ s->session->ciphers=ciphers; ++ s->session->verify_result=X509_V_OK; ++ ++ ciphers=NULL; ++ ++ /* check if some cipher was preferred by call back */ ++ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); ++ if (pref_cipher == NULL) ++ { ++ al=SSL_AD_HANDSHAKE_FAILURE; ++ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); ++ goto f_err; ++ } ++ ++ s->session->cipher=pref_cipher; ++ ++ if (s->cipher_list) ++ sk_SSL_CIPHER_free(s->cipher_list); ++ ++ if (s->cipher_list_by_id) ++ sk_SSL_CIPHER_free(s->cipher_list_by_id); ++ ++ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); ++ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); ++ } ++ } ++ + /* Given s->session->ciphers and SSL_get_ciphers, we must + * pick a cipher */ + +diff -uprN openssl-0.9.8d.orig/ssl/ssl.h openssl-0.9.8d/ssl/ssl.h +--- openssl-0.9.8d.orig/ssl/ssl.h 2006-06-14 06:52:49.000000000 -0700 ++++ openssl-0.9.8d/ssl/ssl.h 2006-12-10 08:20:02.000000000 -0800 +@@ -345,6 +345,7 @@ extern "C" { + * 'struct ssl_st *' function parameters used to prototype callbacks + * in SSL_CTX. */ + typedef struct ssl_st *ssl_crock_st; ++typedef struct tls_extension_st TLS_EXTENSION; + + /* used to hold info on the particular ciphers used */ + typedef struct ssl_cipher_st +@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER) + typedef struct ssl_st SSL; + typedef struct ssl_ctx_st SSL_CTX; + ++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); ++ + /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ + typedef struct ssl_method_st + { +@@ -973,6 +976,15 @@ struct ssl_st + int first_packet; + int client_version; /* what was passed, used for + * SSLv3/TLS rollback check */ ++ ++ /* TLS externsions */ ++ TLS_EXTENSION *tls_extension; ++ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); ++ void *tls_extension_cb_arg; ++ ++ /* TLS pre-shared secret session resumption */ ++ tls_session_secret_cb_fn tls_session_secret_cb; ++ void *tls_session_secret_cb_arg; + }; + + #ifdef __cplusplus +@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v + int SSL_COMP_add_compression_method(int id,void *cm); + #endif + ++/* TLS extensions functions */ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); ++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); ++ ++/* Pre-shared secret session resumption functions */ ++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); ++ + /* BEGIN ERROR CODES */ + /* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. +@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void); + #define SSL_F_TLS1_ENC 210 + #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 + #define SSL_F_WRITE_PENDING 212 ++#define SSL_F_SSL_SET_HELLO_EXTENSION 213 + + /* Reason codes. */ + #define SSL_R_APP_DATA_IN_HANDSHAKE 100 +diff -uprN openssl-0.9.8d.orig/ssl/ssl_err.c openssl-0.9.8d/ssl/ssl_err.c +--- openssl-0.9.8d.orig/ssl/ssl_err.c 2006-01-08 13:52:46.000000000 -0800 ++++ openssl-0.9.8d/ssl/ssl_err.c 2006-12-10 08:20:02.000000000 -0800 +@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]= + {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, + {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, + {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, ++{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, + {0,NULL} + }; + +diff -uprN openssl-0.9.8d.orig/ssl/ssl_sess.c openssl-0.9.8d/ssl/ssl_sess.c +--- openssl-0.9.8d.orig/ssl/ssl_sess.c 2005-12-30 15:51:57.000000000 -0800 ++++ openssl-0.9.8d/ssl/ssl_sess.c 2006-12-10 08:20:02.000000000 -0800 +@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX * + return(s->session_timeout); + } + ++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, ++ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) ++{ ++ if (s == NULL) return(0); ++ s->tls_session_secret_cb = tls_session_secret_cb; ++ s->tls_session_secret_cb_arg = arg; ++ return(1); ++} ++ + typedef struct timeout_param_st + { + SSL_CTX *ctx; +diff -uprN openssl-0.9.8d.orig/ssl/t1_ext.c openssl-0.9.8d/ssl/t1_ext.c +--- openssl-0.9.8d.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800 ++++ openssl-0.9.8d/ssl/t1_ext.c 2006-12-10 08:20:02.000000000 -0800 +@@ -0,0 +1,48 @@ ++ ++#include ++#include "ssl_locl.h" ++ ++ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) ++{ ++ if(s->version >= TLS1_VERSION) ++ { ++ if(s->tls_extension) ++ { ++ OPENSSL_free(s->tls_extension); ++ s->tls_extension = NULL; ++ } ++ ++ if(ext_data) ++ { ++ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); ++ if(!s->tls_extension) ++ { ++ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ ++ s->tls_extension->type = ext_type; ++ s->tls_extension->length = ext_len; ++ s->tls_extension->data = s->tls_extension + 1; ++ memcpy(s->tls_extension->data, ext_data, ext_len); ++ } ++ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg) ++{ ++ if(s->version >= TLS1_VERSION) ++ { ++ s->tls_extension_cb = cb; ++ s->tls_extension_cb_arg = arg; ++ ++ return 1; ++ } ++ ++ return 0; ++} +diff -uprN openssl-0.9.8d.orig/ssl/t1_lib.c openssl-0.9.8d/ssl/t1_lib.c +--- openssl-0.9.8d.orig/ssl/t1_lib.c 2005-08-05 16:52:07.000000000 -0700 ++++ openssl-0.9.8d/ssl/t1_lib.c 2006-12-10 08:20:02.000000000 -0800 +@@ -97,6 +97,10 @@ int tls1_new(SSL *s) + + void tls1_free(SSL *s) + { ++ if(s->tls_extension) ++ { ++ OPENSSL_free(s->tls_extension); ++ } + ssl3_free(s); + } + +diff -uprN openssl-0.9.8d.orig/ssl/tls1.h openssl-0.9.8d/ssl/tls1.h +--- openssl-0.9.8d.orig/ssl/tls1.h 2006-06-14 10:52:01.000000000 -0700 ++++ openssl-0.9.8d/ssl/tls1.h 2006-12-10 08:20:02.000000000 -0800 +@@ -296,6 +296,14 @@ extern "C" { + #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ + #endif + ++/* TLS extension struct */ ++struct tls_extension_st ++{ ++ unsigned short type; ++ unsigned short length; ++ void *data; ++}; ++ + #ifdef __cplusplus + } + #endif +diff -uprN openssl-0.9.8d.orig/util/ssleay.num openssl-0.9.8d/util/ssleay.num +--- openssl-0.9.8d.orig/util/ssleay.num 2005-05-08 17:22:02.000000000 -0700 ++++ openssl-0.9.8d/util/ssleay.num 2006-12-10 08:20:02.000000000 -0800 +@@ -226,3 +226,6 @@ DTLSv1_server_method + SSL_COMP_get_compression_methods 276 EXIST:!VMS:FUNCTION:COMP + SSL_COMP_get_compress_methods 276 EXIST:VMS:FUNCTION:COMP + SSL_SESSION_get_id 277 EXIST::FUNCTION: ++SSL_set_hello_extension 278 EXIST::FUNCTION: ++SSL_set_hello_extension_cb 279 EXIST::FUNCTION: ++SSL_set_session_secret_cb 280 EXIST::FUNCTION: diff --git a/contrib/wpa/patches/openssl-0.9.8e-tls-extensions.patch b/contrib/wpa/patches/openssl-0.9.8e-tls-extensions.patch new file mode 100644 index 000000000000..ede053f779b6 --- /dev/null +++ b/contrib/wpa/patches/openssl-0.9.8e-tls-extensions.patch @@ -0,0 +1,353 @@ +This patch is adding support for TLS hello extensions and externally +generated pre-shared key material to OpenSSL 0.9.8e. This is +based on the patch from Alexey Kobozev +(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). + + + +diff -uprN openssl-0.9.8e.orig/ssl/Makefile openssl-0.9.8e/ssl/Makefile +--- openssl-0.9.8e.orig/ssl/Makefile 2006-02-03 17:49:35.000000000 -0800 ++++ openssl-0.9.8e/ssl/Makefile 2007-03-22 20:23:19.000000000 -0700 +@@ -24,7 +24,7 @@ LIBSRC= \ + s2_meth.c s2_srvr.c s2_clnt.c s2_lib.c s2_enc.c s2_pkt.c \ + s3_meth.c s3_srvr.c s3_clnt.c s3_lib.c s3_enc.c s3_pkt.c s3_both.c \ + s23_meth.c s23_srvr.c s23_clnt.c s23_lib.c s23_pkt.c \ +- t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c \ ++ t1_meth.c t1_srvr.c t1_clnt.c t1_lib.c t1_enc.c t1_ext.c \ + d1_meth.c d1_srvr.c d1_clnt.c d1_lib.c d1_pkt.c \ + d1_both.c d1_enc.c \ + ssl_lib.c ssl_err2.c ssl_cert.c ssl_sess.c \ +@@ -35,7 +35,7 @@ LIBOBJ= \ + s2_meth.o s2_srvr.o s2_clnt.o s2_lib.o s2_enc.o s2_pkt.o \ + s3_meth.o s3_srvr.o s3_clnt.o s3_lib.o s3_enc.o s3_pkt.o s3_both.o \ + s23_meth.o s23_srvr.o s23_clnt.o s23_lib.o s23_pkt.o \ +- t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o \ ++ t1_meth.o t1_srvr.o t1_clnt.o t1_lib.o t1_enc.o t1_ext.o \ + d1_meth.o d1_srvr.o d1_clnt.o d1_lib.o d1_pkt.o \ + d1_both.o d1_enc.o \ + ssl_lib.o ssl_err2.o ssl_cert.o ssl_sess.o \ +@@ -968,3 +968,4 @@ t1_srvr.o: ../include/openssl/ssl23.h .. + t1_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h + t1_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h + t1_srvr.o: ../include/openssl/x509_vfy.h ssl_locl.h t1_srvr.c ++t1_ext.o: t1_ext.c ssl_locl.h +diff -uprN openssl-0.9.8e.orig/ssl/s3_clnt.c openssl-0.9.8e/ssl/s3_clnt.c +--- openssl-0.9.8e.orig/ssl/s3_clnt.c 2006-09-28 05:23:15.000000000 -0700 ++++ openssl-0.9.8e/ssl/s3_clnt.c 2007-03-22 20:23:19.000000000 -0700 +@@ -601,6 +601,20 @@ int ssl3_client_hello(SSL *s) + #endif + *(p++)=0; /* Add the NULL method */ + ++ /* send client hello extensions if any */ ++ if (s->version >= TLS1_VERSION && s->tls_extension) ++ { ++ // set the total extensions length ++ s2n(s->tls_extension->length + 4, p); ++ ++ // put the extensions with type and length ++ s2n(s->tls_extension->type, p); ++ s2n(s->tls_extension->length, p); ++ ++ memcpy(p, s->tls_extension->data, s->tls_extension->length); ++ p+=s->tls_extension->length; ++ } ++ + l=(p-d); + d=buf; + *(d++)=SSL3_MT_CLIENT_HELLO; +@@ -623,7 +637,7 @@ int ssl3_get_server_hello(SSL *s) + STACK_OF(SSL_CIPHER) *sk; + SSL_CIPHER *c; + unsigned char *p,*d; +- int i,al,ok; ++ int i,al,ok,pre_shared; + unsigned int j; + long n; + #ifndef OPENSSL_NO_COMP +@@ -690,7 +704,24 @@ int ssl3_get_server_hello(SSL *s) + goto f_err; + } + +- if (j != 0 && j == s->session->session_id_length ++ /* check if we want to resume the session based on external pre-shared secret */ ++ pre_shared = 0; ++ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, ++ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) ++ { ++ s->hit=1; ++ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); ++ s->session->session_id_length = j; ++ memcpy(s->session->session_id, p, j); ++ pre_shared = 1; ++ } ++ } ++ ++ if ((pre_shared || j != 0) && j == s->session->session_id_length + && memcmp(p,s->session->session_id,j) == 0) + { + if(s->sid_ctx_length != s->session->sid_ctx_length +diff -uprN openssl-0.9.8e.orig/ssl/s3_srvr.c openssl-0.9.8e/ssl/s3_srvr.c +--- openssl-0.9.8e.orig/ssl/s3_srvr.c 2007-02-07 12:36:40.000000000 -0800 ++++ openssl-0.9.8e/ssl/s3_srvr.c 2007-03-22 20:23:19.000000000 -0700 +@@ -945,6 +945,75 @@ int ssl3_get_client_hello(SSL *s) + } + #endif + ++ /* Check for TLS client hello extension here */ ++ if (p < (d+n) && s->version >= TLS1_VERSION) ++ { ++ if (s->tls_extension_cb) ++ { ++ TLS_EXTENSION tls_ext; ++ unsigned short ext_total_len; ++ ++ n2s(p, ext_total_len); ++ n2s(p, tls_ext.type); ++ n2s(p, tls_ext.length); ++ ++ // sanity check in TLS extension len ++ if (tls_ext.length > (d+n) - p) ++ { ++ // just cut the lenth to packet border ++ tls_ext.length = (d+n) - p; ++ } ++ ++ tls_ext.data = p; ++ ++ // returns an alert code or 0 ++ al = s->tls_extension_cb(s, &tls_ext, s->tls_extension_cb_arg); ++ if (al != 0) ++ { ++ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PEER_ERROR); ++ goto f_err; ++ } ++ } ++ } ++ ++ /* Check if we want to use external pre-shared secret for this handshake */ ++ /* for not reused session only */ ++ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, ++ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) ++ { ++ s->hit=1; ++ s->session->ciphers=ciphers; ++ s->session->verify_result=X509_V_OK; ++ ++ ciphers=NULL; ++ ++ /* check if some cipher was preferred by call back */ ++ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); ++ if (pref_cipher == NULL) ++ { ++ al=SSL_AD_HANDSHAKE_FAILURE; ++ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); ++ goto f_err; ++ } ++ ++ s->session->cipher=pref_cipher; ++ ++ if (s->cipher_list) ++ sk_SSL_CIPHER_free(s->cipher_list); ++ ++ if (s->cipher_list_by_id) ++ sk_SSL_CIPHER_free(s->cipher_list_by_id); ++ ++ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); ++ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); ++ } ++ } ++ + /* Given s->session->ciphers and SSL_get_ciphers, we must + * pick a cipher */ + +diff -uprN openssl-0.9.8e.orig/ssl/ssl.h openssl-0.9.8e/ssl/ssl.h +--- openssl-0.9.8e.orig/ssl/ssl.h 2007-02-19 09:55:07.000000000 -0800 ++++ openssl-0.9.8e/ssl/ssl.h 2007-03-22 20:23:19.000000000 -0700 +@@ -345,6 +345,7 @@ extern "C" { + * 'struct ssl_st *' function parameters used to prototype callbacks + * in SSL_CTX. */ + typedef struct ssl_st *ssl_crock_st; ++typedef struct tls_extension_st TLS_EXTENSION; + + /* used to hold info on the particular ciphers used */ + typedef struct ssl_cipher_st +@@ -366,6 +367,8 @@ DECLARE_STACK_OF(SSL_CIPHER) + typedef struct ssl_st SSL; + typedef struct ssl_ctx_st SSL_CTX; + ++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); ++ + /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ + typedef struct ssl_method_st + { +@@ -973,6 +976,15 @@ struct ssl_st + int first_packet; + int client_version; /* what was passed, used for + * SSLv3/TLS rollback check */ ++ ++ /* TLS externsions */ ++ TLS_EXTENSION *tls_extension; ++ int (*tls_extension_cb)(SSL *s, TLS_EXTENSION *tls_ext, void *arg); ++ void *tls_extension_cb_arg; ++ ++ /* TLS pre-shared secret session resumption */ ++ tls_session_secret_cb_fn tls_session_secret_cb; ++ void *tls_session_secret_cb_arg; + }; + + #ifdef __cplusplus +@@ -1538,6 +1550,13 @@ void *SSL_COMP_get_compression_methods(v + int SSL_COMP_add_compression_method(int id,void *cm); + #endif + ++/* TLS extensions functions */ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); ++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg); ++ ++/* Pre-shared secret session resumption functions */ ++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); ++ + /* BEGIN ERROR CODES */ + /* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. +@@ -1719,6 +1738,7 @@ void ERR_load_SSL_strings(void); + #define SSL_F_TLS1_ENC 210 + #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 + #define SSL_F_WRITE_PENDING 212 ++#define SSL_F_SSL_SET_HELLO_EXTENSION 213 + + /* Reason codes. */ + #define SSL_R_APP_DATA_IN_HANDSHAKE 100 +diff -uprN openssl-0.9.8e.orig/ssl/ssl_err.c openssl-0.9.8e/ssl/ssl_err.c +--- openssl-0.9.8e.orig/ssl/ssl_err.c 2006-11-21 12:14:46.000000000 -0800 ++++ openssl-0.9.8e/ssl/ssl_err.c 2007-03-22 20:23:19.000000000 -0700 +@@ -242,6 +242,7 @@ static ERR_STRING_DATA SSL_str_functs[]= + {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, + {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, + {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, ++{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, + {0,NULL} + }; + +diff -uprN openssl-0.9.8e.orig/ssl/ssl_sess.c openssl-0.9.8e/ssl/ssl_sess.c +--- openssl-0.9.8e.orig/ssl/ssl_sess.c 2007-02-10 02:40:24.000000000 -0800 ++++ openssl-0.9.8e/ssl/ssl_sess.c 2007-03-22 20:23:19.000000000 -0700 +@@ -656,6 +656,15 @@ long SSL_CTX_get_timeout(const SSL_CTX * + return(s->session_timeout); + } + ++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, ++ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) ++{ ++ if (s == NULL) return(0); ++ s->tls_session_secret_cb = tls_session_secret_cb; ++ s->tls_session_secret_cb_arg = arg; ++ return(1); ++} ++ + typedef struct timeout_param_st + { + SSL_CTX *ctx; +diff -uprN openssl-0.9.8e.orig/ssl/t1_ext.c openssl-0.9.8e/ssl/t1_ext.c +--- openssl-0.9.8e.orig/ssl/t1_ext.c 1969-12-31 16:00:00.000000000 -0800 ++++ openssl-0.9.8e/ssl/t1_ext.c 2007-03-22 20:23:19.000000000 -0700 +@@ -0,0 +1,48 @@ ++ ++#include ++#include "ssl_locl.h" ++ ++ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) ++{ ++ if(s->version >= TLS1_VERSION) ++ { ++ if(s->tls_extension) ++ { ++ OPENSSL_free(s->tls_extension); ++ s->tls_extension = NULL; ++ } ++ ++ if(ext_data) ++ { ++ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); ++ if(!s->tls_extension) ++ { ++ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ ++ s->tls_extension->type = ext_type; ++ s->tls_extension->length = ext_len; ++ s->tls_extension->data = s->tls_extension + 1; ++ memcpy(s->tls_extension->data, ext_data, ext_len); ++ } ++ ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int SSL_set_hello_extension_cb(SSL *s, int (*cb)(SSL *, TLS_EXTENSION *, void *), void *arg) ++{ ++ if(s->version >= TLS1_VERSION) ++ { ++ s->tls_extension_cb = cb; ++ s->tls_extension_cb_arg = arg; ++ ++ return 1; ++ } ++ ++ return 0; ++} +diff -uprN openssl-0.9.8e.orig/ssl/t1_lib.c openssl-0.9.8e/ssl/t1_lib.c +--- openssl-0.9.8e.orig/ssl/t1_lib.c 2007-01-21 08:07:25.000000000 -0800 ++++ openssl-0.9.8e/ssl/t1_lib.c 2007-03-22 20:23:19.000000000 -0700 +@@ -97,6 +97,10 @@ int tls1_new(SSL *s) + + void tls1_free(SSL *s) + { ++ if(s->tls_extension) ++ { ++ OPENSSL_free(s->tls_extension); ++ } + ssl3_free(s); + } + +diff -uprN openssl-0.9.8e.orig/ssl/tls1.h openssl-0.9.8e/ssl/tls1.h +--- openssl-0.9.8e.orig/ssl/tls1.h 2006-06-14 10:52:01.000000000 -0700 ++++ openssl-0.9.8e/ssl/tls1.h 2007-03-22 20:23:19.000000000 -0700 +@@ -296,6 +296,14 @@ extern "C" { + #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ + #endif + ++/* TLS extension struct */ ++struct tls_extension_st ++{ ++ unsigned short type; ++ unsigned short length; ++ void *data; ++}; ++ + #ifdef __cplusplus + } + #endif +diff -uprN openssl-0.9.8e.orig/util/ssleay.num openssl-0.9.8e/util/ssleay.num +--- openssl-0.9.8e.orig/util/ssleay.num 2006-11-30 05:04:43.000000000 -0800 ++++ openssl-0.9.8e/util/ssleay.num 2007-03-22 20:24:07.000000000 -0700 +@@ -238,3 +238,6 @@ SSL_CTX_set_info_callback + SSL_CTX_sess_get_new_cb 287 EXIST::FUNCTION: + SSL_CTX_get_client_cert_cb 288 EXIST::FUNCTION: + SSL_CTX_sess_get_remove_cb 289 EXIST::FUNCTION: ++SSL_set_hello_extension 290 EXIST::FUNCTION: ++SSL_set_hello_extension_cb 291 EXIST::FUNCTION: ++SSL_set_session_secret_cb 292 EXIST::FUNCTION: diff --git a/contrib/wpa/patches/openssl-0.9.8g-tls-extensions.patch b/contrib/wpa/patches/openssl-0.9.8g-tls-extensions.patch new file mode 100644 index 000000000000..8ccbfaa29ddf --- /dev/null +++ b/contrib/wpa/patches/openssl-0.9.8g-tls-extensions.patch @@ -0,0 +1,330 @@ +This patch adds support for TLS SessionTicket extension (RFC 5077) for +the parts used by EAP-FAST (RFC 4851). + +This is based on the patch from Alexey Kobozev +(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). + +OpenSSL 0.9.8g does not enable TLS extension support by default, so it +will need to be enabled by adding enable-tlsext to config script +command line. + + +diff -upr openssl-0.9.8g.orig/ssl/s3_clnt.c openssl-0.9.8g/ssl/s3_clnt.c +--- openssl-0.9.8g.orig/ssl/s3_clnt.c 2007-08-31 03:28:51.000000000 +0300 ++++ openssl-0.9.8g/ssl/s3_clnt.c 2008-04-15 17:11:46.000000000 +0300 +@@ -727,6 +727,20 @@ int ssl3_get_server_hello(SSL *s) + goto f_err; + } + ++#ifndef OPENSSL_NO_TLSEXT ++ /* check if we want to resume the session based on external pre-shared secret */ ++ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, ++ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) ++ { ++ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); ++ } ++ } ++#endif /* OPENSSL_NO_TLSEXT */ ++ + if (j != 0 && j == s->session->session_id_length + && memcmp(p,s->session->session_id,j) == 0) + { +diff -upr openssl-0.9.8g.orig/ssl/s3_srvr.c openssl-0.9.8g/ssl/s3_srvr.c +--- openssl-0.9.8g.orig/ssl/s3_srvr.c 2007-09-30 21:55:59.000000000 +0300 ++++ openssl-0.9.8g/ssl/s3_srvr.c 2008-04-15 17:10:37.000000000 +0300 +@@ -928,6 +928,59 @@ int ssl3_get_client_hello(SSL *s) + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); + goto err; + } ++ ++ /* Check if we want to use external pre-shared secret for this ++ * handshake for not reused session only. We need to generate ++ * server_random before calling tls_session_secret_cb in order to allow ++ * SessionTicket processing to use it in key derivation. */ ++ { ++ unsigned long Time; ++ unsigned char *pos; ++ Time=(unsigned long)time(NULL); /* Time */ ++ pos=s->s3->server_random; ++ l2n(Time,pos); ++ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0) ++ { ++ al=SSL_AD_INTERNAL_ERROR; ++ goto f_err; ++ } ++ } ++ ++ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, ++ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) ++ { ++ s->hit=1; ++ s->session->ciphers=ciphers; ++ s->session->verify_result=X509_V_OK; ++ ++ ciphers=NULL; ++ ++ /* check if some cipher was preferred by call back */ ++ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); ++ if (pref_cipher == NULL) ++ { ++ al=SSL_AD_HANDSHAKE_FAILURE; ++ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); ++ goto f_err; ++ } ++ ++ s->session->cipher=pref_cipher; ++ ++ if (s->cipher_list) ++ sk_SSL_CIPHER_free(s->cipher_list); ++ ++ if (s->cipher_list_by_id) ++ sk_SSL_CIPHER_free(s->cipher_list_by_id); ++ ++ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); ++ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); ++ } ++ } + #endif + /* Worst case, we will use the NULL compression, but if we have other + * options, we will now look for them. We have i-1 compression +@@ -1066,16 +1119,22 @@ int ssl3_send_server_hello(SSL *s) + unsigned char *buf; + unsigned char *p,*d; + int i,sl; +- unsigned long l,Time; ++ unsigned long l; ++#ifdef OPENSSL_NO_TLSEXT ++ unsigned long Time; ++#endif + + if (s->state == SSL3_ST_SW_SRVR_HELLO_A) + { + buf=(unsigned char *)s->init_buf->data; ++#ifdef OPENSSL_NO_TLSEXT + p=s->s3->server_random; ++ /* Generate server_random if it was not needed previously */ + Time=(unsigned long)time(NULL); /* Time */ + l2n(Time,p); + if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) + return -1; ++#endif + /* Do the message type and length last */ + d=p= &(buf[4]); + +diff -upr openssl-0.9.8g.orig/ssl/ssl.h openssl-0.9.8g/ssl/ssl.h +--- openssl-0.9.8g.orig/ssl/ssl.h 2007-10-19 10:42:38.000000000 +0300 ++++ openssl-0.9.8g/ssl/ssl.h 2008-04-15 17:10:37.000000000 +0300 +@@ -342,6 +342,7 @@ extern "C" { + * 'struct ssl_st *' function parameters used to prototype callbacks + * in SSL_CTX. */ + typedef struct ssl_st *ssl_crock_st; ++typedef struct tls_extension_st TLS_EXTENSION; + + /* used to hold info on the particular ciphers used */ + typedef struct ssl_cipher_st +@@ -363,6 +364,8 @@ DECLARE_STACK_OF(SSL_CIPHER) + typedef struct ssl_st SSL; + typedef struct ssl_ctx_st SSL_CTX; + ++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); ++ + /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ + typedef struct ssl_method_st + { +@@ -1004,6 +1007,14 @@ struct ssl_st + */ + /* RFC4507 session ticket expected to be received or sent */ + int tlsext_ticket_expected; ++ ++ /* TLS extensions */ ++ TLS_EXTENSION *tls_extension; ++ ++ /* TLS pre-shared secret session resumption */ ++ tls_session_secret_cb_fn tls_session_secret_cb; ++ void *tls_session_secret_cb_arg; ++ + SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ + #define session_ctx initial_ctx + #else +@@ -1589,6 +1600,12 @@ void *SSL_COMP_get_compression_methods(v + int SSL_COMP_add_compression_method(int id,void *cm); + #endif + ++/* TLS extensions functions */ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); ++ ++/* Pre-shared secret session resumption functions */ ++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); ++ + /* BEGIN ERROR CODES */ + /* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. +@@ -1778,6 +1795,7 @@ void ERR_load_SSL_strings(void); + #define SSL_F_TLS1_ENC 210 + #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 + #define SSL_F_WRITE_PENDING 212 ++#define SSL_F_SSL_SET_HELLO_EXTENSION 213 + + /* Reason codes. */ + #define SSL_R_APP_DATA_IN_HANDSHAKE 100 +diff -upr openssl-0.9.8g.orig/ssl/ssl_err.c openssl-0.9.8g/ssl/ssl_err.c +--- openssl-0.9.8g.orig/ssl/ssl_err.c 2007-10-11 17:36:59.000000000 +0300 ++++ openssl-0.9.8g/ssl/ssl_err.c 2008-04-15 17:10:37.000000000 +0300 +@@ -250,6 +250,7 @@ static ERR_STRING_DATA SSL_str_functs[]= + {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, + {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, + {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, ++{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, + {0,NULL} + }; + +diff -upr openssl-0.9.8g.orig/ssl/ssl_sess.c openssl-0.9.8g/ssl/ssl_sess.c +--- openssl-0.9.8g.orig/ssl/ssl_sess.c 2007-10-19 10:36:34.000000000 +0300 ++++ openssl-0.9.8g/ssl/ssl_sess.c 2008-04-15 17:10:37.000000000 +0300 +@@ -704,6 +704,52 @@ long SSL_CTX_get_timeout(const SSL_CTX * + return(s->session_timeout); + } + ++#ifndef OPENSSL_NO_TLSEXT ++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, ++ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) ++{ ++ if (s == NULL) return(0); ++ s->tls_session_secret_cb = tls_session_secret_cb; ++ s->tls_session_secret_cb_arg = arg; ++ return(1); ++} ++ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) ++{ ++ if(s->version >= TLS1_VERSION) ++ { ++ if(s->tls_extension) ++ { ++ OPENSSL_free(s->tls_extension); ++ s->tls_extension = NULL; ++ } ++ ++ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); ++ if(!s->tls_extension) ++ { ++ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ ++ s->tls_extension->type = ext_type; ++ ++ if(ext_data) ++ { ++ s->tls_extension->length = ext_len; ++ s->tls_extension->data = s->tls_extension + 1; ++ memcpy(s->tls_extension->data, ext_data, ext_len); ++ } else { ++ s->tls_extension->length = 0; ++ s->tls_extension->data = NULL; ++ } ++ ++ return 1; ++ } ++ ++ return 0; ++} ++#endif /* OPENSSL_NO_TLSEXT */ ++ + typedef struct timeout_param_st + { + SSL_CTX *ctx; +diff -upr openssl-0.9.8g.orig/ssl/t1_lib.c openssl-0.9.8g/ssl/t1_lib.c +--- openssl-0.9.8g.orig/ssl/t1_lib.c 2007-10-19 10:44:10.000000000 +0300 ++++ openssl-0.9.8g/ssl/t1_lib.c 2008-04-15 17:10:37.000000000 +0300 +@@ -105,6 +105,12 @@ int tls1_new(SSL *s) + + void tls1_free(SSL *s) + { ++#ifndef OPENSSL_NO_TLSEXT ++ if(s->tls_extension) ++ { ++ OPENSSL_free(s->tls_extension); ++ } ++#endif + ssl3_free(s); + } + +@@ -174,8 +180,24 @@ unsigned char *ssl_add_clienthello_tlsex + int ticklen; + if (s->session && s->session->tlsext_tick) + ticklen = s->session->tlsext_ticklen; ++ else if (s->session && s->tls_extension && ++ s->tls_extension->type == TLSEXT_TYPE_session_ticket && ++ s->tls_extension->data) ++ { ++ ticklen = s->tls_extension->length; ++ s->session->tlsext_tick = OPENSSL_malloc(ticklen); ++ if (!s->session->tlsext_tick) ++ return NULL; ++ memcpy(s->session->tlsext_tick, s->tls_extension->data, ++ ticklen); ++ s->session->tlsext_ticklen = ticklen; ++ } + else + ticklen = 0; ++ if (ticklen == 0 && s->tls_extension && ++ s->tls_extension->type == TLSEXT_TYPE_session_ticket && ++ s->tls_extension->data == NULL) ++ goto skip_ext; + /* Check for enough room 2 for extension type, 2 for len + * rest for ticket + */ +@@ -189,6 +211,7 @@ unsigned char *ssl_add_clienthello_tlsex + ret += ticklen; + } + } ++ skip_ext: + + if ((extdatalen = ret-p-2)== 0) + return p; +@@ -543,6 +566,8 @@ int tls1_process_ticket(SSL *s, unsigned + s->tlsext_ticket_expected = 1; + return 0; /* Cache miss */ + } ++ if (s->tls_session_secret_cb) ++ return 0; + return tls_decrypt_ticket(s, p, size, session_id, len, + ret); + } +diff -upr openssl-0.9.8g.orig/ssl/tls1.h openssl-0.9.8g/ssl/tls1.h +--- openssl-0.9.8g.orig/ssl/tls1.h 2007-08-28 04:12:44.000000000 +0300 ++++ openssl-0.9.8g/ssl/tls1.h 2008-04-15 17:10:37.000000000 +0300 +@@ -365,6 +365,14 @@ SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SER + #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ + #endif + ++/* TLS extension struct */ ++struct tls_extension_st ++{ ++ unsigned short type; ++ unsigned short length; ++ void *data; ++}; ++ + #ifdef __cplusplus + } + #endif +diff -upr openssl-0.9.8g.orig/util/ssleay.num openssl-0.9.8g/util/ssleay.num +--- openssl-0.9.8g.orig/util/ssleay.num 2007-08-13 01:31:16.000000000 +0300 ++++ openssl-0.9.8g/util/ssleay.num 2008-04-15 17:10:37.000000000 +0300 +@@ -241,3 +241,5 @@ SSL_CTX_sess_get_remove_cb + SSL_set_SSL_CTX 290 EXIST::FUNCTION: + SSL_get_servername 291 EXIST::FUNCTION:TLSEXT + SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT ++SSL_set_hello_extension 305 EXIST::FUNCTION:TLSEXT ++SSL_set_session_secret_cb 306 EXIST::FUNCTION:TLSEXT diff --git a/contrib/wpa/patches/openssl-0.9.8h-tls-extensions.patch b/contrib/wpa/patches/openssl-0.9.8h-tls-extensions.patch new file mode 100644 index 000000000000..c68f2279b762 --- /dev/null +++ b/contrib/wpa/patches/openssl-0.9.8h-tls-extensions.patch @@ -0,0 +1,344 @@ +This patch adds support for TLS SessionTicket extension (RFC 5077) for +the parts used by EAP-FAST (RFC 4851). + +This is based on the patch from Alexey Kobozev +(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). + +OpenSSL 0.9.8h does not enable TLS extension support by default, so it +will need to be enabled by adding enable-tlsext to config script +command line. + + +diff -upr openssl-0.9.8h.orig/ssl/s3_clnt.c openssl-0.9.8h/ssl/s3_clnt.c +--- openssl-0.9.8h.orig/ssl/s3_clnt.c 2008-05-28 10:29:27.000000000 +0300 ++++ openssl-0.9.8h/ssl/s3_clnt.c 2008-05-29 10:44:25.000000000 +0300 +@@ -752,6 +752,20 @@ int ssl3_get_server_hello(SSL *s) + goto f_err; + } + ++#ifndef OPENSSL_NO_TLSEXT ++ /* check if we want to resume the session based on external pre-shared secret */ ++ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, ++ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) ++ { ++ s->session->cipher=pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s,p+j); ++ } ++ } ++#endif /* OPENSSL_NO_TLSEXT */ ++ + if (j != 0 && j == s->session->session_id_length + && memcmp(p,s->session->session_id,j) == 0) + { +@@ -2693,11 +2707,8 @@ static int ssl3_check_finished(SSL *s) + { + int ok; + long n; +- /* If we have no ticket or session ID is non-zero length (a match of +- * a non-zero session length would never reach here) it cannot be a +- * resumed session. +- */ +- if (!s->session->tlsext_tick || s->session->session_id_length) ++ /* If we have no ticket it cannot be a resumed session. */ ++ if (!s->session->tlsext_tick) + return 1; + /* this function is called when we really expect a Certificate + * message, so permit appropriate message length */ +diff -upr openssl-0.9.8h.orig/ssl/s3_srvr.c openssl-0.9.8h/ssl/s3_srvr.c +--- openssl-0.9.8h.orig/ssl/s3_srvr.c 2008-04-30 19:11:32.000000000 +0300 ++++ openssl-0.9.8h/ssl/s3_srvr.c 2008-05-28 18:49:34.000000000 +0300 +@@ -959,6 +959,59 @@ int ssl3_get_client_hello(SSL *s) + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); + goto err; + } ++ ++ /* Check if we want to use external pre-shared secret for this ++ * handshake for not reused session only. We need to generate ++ * server_random before calling tls_session_secret_cb in order to allow ++ * SessionTicket processing to use it in key derivation. */ ++ { ++ unsigned long Time; ++ unsigned char *pos; ++ Time=(unsigned long)time(NULL); /* Time */ ++ pos=s->s3->server_random; ++ l2n(Time,pos); ++ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0) ++ { ++ al=SSL_AD_INTERNAL_ERROR; ++ goto f_err; ++ } ++ } ++ ++ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, ++ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) ++ { ++ s->hit=1; ++ s->session->ciphers=ciphers; ++ s->session->verify_result=X509_V_OK; ++ ++ ciphers=NULL; ++ ++ /* check if some cipher was preferred by call back */ ++ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); ++ if (pref_cipher == NULL) ++ { ++ al=SSL_AD_HANDSHAKE_FAILURE; ++ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); ++ goto f_err; ++ } ++ ++ s->session->cipher=pref_cipher; ++ ++ if (s->cipher_list) ++ sk_SSL_CIPHER_free(s->cipher_list); ++ ++ if (s->cipher_list_by_id) ++ sk_SSL_CIPHER_free(s->cipher_list_by_id); ++ ++ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); ++ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); ++ } ++ } + #endif + /* Worst case, we will use the NULL compression, but if we have other + * options, we will now look for them. We have i-1 compression +@@ -1097,16 +1150,22 @@ int ssl3_send_server_hello(SSL *s) + unsigned char *buf; + unsigned char *p,*d; + int i,sl; +- unsigned long l,Time; ++ unsigned long l; ++#ifdef OPENSSL_NO_TLSEXT ++ unsigned long Time; ++#endif + + if (s->state == SSL3_ST_SW_SRVR_HELLO_A) + { + buf=(unsigned char *)s->init_buf->data; ++#ifdef OPENSSL_NO_TLSEXT + p=s->s3->server_random; ++ /* Generate server_random if it was not needed previously */ + Time=(unsigned long)time(NULL); /* Time */ + l2n(Time,p); + if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) + return -1; ++#endif + /* Do the message type and length last */ + d=p= &(buf[4]); + +diff -upr openssl-0.9.8h.orig/ssl/ssl.h openssl-0.9.8h/ssl/ssl.h +--- openssl-0.9.8h.orig/ssl/ssl.h 2008-04-30 19:11:32.000000000 +0300 ++++ openssl-0.9.8h/ssl/ssl.h 2008-05-28 18:49:34.000000000 +0300 +@@ -343,6 +343,7 @@ extern "C" { + * 'struct ssl_st *' function parameters used to prototype callbacks + * in SSL_CTX. */ + typedef struct ssl_st *ssl_crock_st; ++typedef struct tls_extension_st TLS_EXTENSION; + + /* used to hold info on the particular ciphers used */ + typedef struct ssl_cipher_st +@@ -364,6 +365,8 @@ DECLARE_STACK_OF(SSL_CIPHER) + typedef struct ssl_st SSL; + typedef struct ssl_ctx_st SSL_CTX; + ++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); ++ + /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ + typedef struct ssl_method_st + { +@@ -1027,6 +1030,14 @@ struct ssl_st + + /* RFC4507 session ticket expected to be received or sent */ + int tlsext_ticket_expected; ++ ++ /* TLS extensions */ ++ TLS_EXTENSION *tls_extension; ++ ++ /* TLS pre-shared secret session resumption */ ++ tls_session_secret_cb_fn tls_session_secret_cb; ++ void *tls_session_secret_cb_arg; ++ + SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ + #define session_ctx initial_ctx + #else +@@ -1625,6 +1636,12 @@ void *SSL_COMP_get_compression_methods(v + int SSL_COMP_add_compression_method(int id,void *cm); + #endif + ++/* TLS extensions functions */ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); ++ ++/* Pre-shared secret session resumption functions */ ++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); ++ + /* BEGIN ERROR CODES */ + /* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. +@@ -1815,6 +1832,7 @@ void ERR_load_SSL_strings(void); + #define SSL_F_TLS1_ENC 210 + #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 + #define SSL_F_WRITE_PENDING 212 ++#define SSL_F_SSL_SET_HELLO_EXTENSION 213 + + /* Reason codes. */ + #define SSL_R_APP_DATA_IN_HANDSHAKE 100 +diff -upr openssl-0.9.8h.orig/ssl/ssl_err.c openssl-0.9.8h/ssl/ssl_err.c +--- openssl-0.9.8h.orig/ssl/ssl_err.c 2007-10-12 03:00:30.000000000 +0300 ++++ openssl-0.9.8h/ssl/ssl_err.c 2008-05-28 18:49:34.000000000 +0300 +@@ -251,6 +251,7 @@ static ERR_STRING_DATA SSL_str_functs[]= + {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, + {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, + {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, ++{ERR_FUNC(SSL_F_SSL_SET_HELLO_EXTENSION), "SSL_set_hello_extension"}, + {0,NULL} + }; + +diff -upr openssl-0.9.8h.orig/ssl/ssl_sess.c openssl-0.9.8h/ssl/ssl_sess.c +--- openssl-0.9.8h.orig/ssl/ssl_sess.c 2007-10-17 20:30:15.000000000 +0300 ++++ openssl-0.9.8h/ssl/ssl_sess.c 2008-05-28 18:49:34.000000000 +0300 +@@ -704,6 +704,52 @@ long SSL_CTX_get_timeout(const SSL_CTX * + return(s->session_timeout); + } + ++#ifndef OPENSSL_NO_TLSEXT ++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, ++ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) ++{ ++ if (s == NULL) return(0); ++ s->tls_session_secret_cb = tls_session_secret_cb; ++ s->tls_session_secret_cb_arg = arg; ++ return(1); ++} ++ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) ++{ ++ if(s->version >= TLS1_VERSION) ++ { ++ if(s->tls_extension) ++ { ++ OPENSSL_free(s->tls_extension); ++ s->tls_extension = NULL; ++ } ++ ++ s->tls_extension = OPENSSL_malloc(sizeof(TLS_EXTENSION) + ext_len); ++ if(!s->tls_extension) ++ { ++ SSLerr(SSL_F_SSL_SET_HELLO_EXTENSION, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ ++ s->tls_extension->type = ext_type; ++ ++ if(ext_data) ++ { ++ s->tls_extension->length = ext_len; ++ s->tls_extension->data = s->tls_extension + 1; ++ memcpy(s->tls_extension->data, ext_data, ext_len); ++ } else { ++ s->tls_extension->length = 0; ++ s->tls_extension->data = NULL; ++ } ++ ++ return 1; ++ } ++ ++ return 0; ++} ++#endif /* OPENSSL_NO_TLSEXT */ ++ + typedef struct timeout_param_st + { + SSL_CTX *ctx; +diff -upr openssl-0.9.8h.orig/ssl/t1_lib.c openssl-0.9.8h/ssl/t1_lib.c +--- openssl-0.9.8h.orig/ssl/t1_lib.c 2008-05-28 10:26:33.000000000 +0300 ++++ openssl-0.9.8h/ssl/t1_lib.c 2008-05-28 18:49:34.000000000 +0300 +@@ -106,6 +106,12 @@ int tls1_new(SSL *s) + + void tls1_free(SSL *s) + { ++#ifndef OPENSSL_NO_TLSEXT ++ if(s->tls_extension) ++ { ++ OPENSSL_free(s->tls_extension); ++ } ++#endif + ssl3_free(s); + } + +@@ -175,8 +181,24 @@ unsigned char *ssl_add_clienthello_tlsex + int ticklen; + if (s->session && s->session->tlsext_tick) + ticklen = s->session->tlsext_ticklen; ++ else if (s->session && s->tls_extension && ++ s->tls_extension->type == TLSEXT_TYPE_session_ticket && ++ s->tls_extension->data) ++ { ++ ticklen = s->tls_extension->length; ++ s->session->tlsext_tick = OPENSSL_malloc(ticklen); ++ if (!s->session->tlsext_tick) ++ return NULL; ++ memcpy(s->session->tlsext_tick, s->tls_extension->data, ++ ticklen); ++ s->session->tlsext_ticklen = ticklen; ++ } + else + ticklen = 0; ++ if (ticklen == 0 && s->tls_extension && ++ s->tls_extension->type == TLSEXT_TYPE_session_ticket && ++ s->tls_extension->data == NULL) ++ goto skip_ext; + /* Check for enough room 2 for extension type, 2 for len + * rest for ticket + */ +@@ -190,6 +212,7 @@ unsigned char *ssl_add_clienthello_tlsex + ret += ticklen; + } + } ++ skip_ext: + + if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) + { +@@ -774,6 +797,8 @@ int tls1_process_ticket(SSL *s, unsigned + s->tlsext_ticket_expected = 1; + return 0; /* Cache miss */ + } ++ if (s->tls_session_secret_cb) ++ return 0; + return tls_decrypt_ticket(s, p, size, session_id, len, + ret); + } +diff -upr openssl-0.9.8h.orig/ssl/tls1.h openssl-0.9.8h/ssl/tls1.h +--- openssl-0.9.8h.orig/ssl/tls1.h 2008-04-30 19:11:33.000000000 +0300 ++++ openssl-0.9.8h/ssl/tls1.h 2008-05-28 18:49:34.000000000 +0300 +@@ -398,6 +398,14 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T + #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ + #endif + ++/* TLS extension struct */ ++struct tls_extension_st ++{ ++ unsigned short type; ++ unsigned short length; ++ void *data; ++}; ++ + #ifdef __cplusplus + } + #endif +diff -upr openssl-0.9.8h.orig/util/ssleay.num openssl-0.9.8h/util/ssleay.num +--- openssl-0.9.8h.orig/util/ssleay.num 2007-08-13 01:31:16.000000000 +0300 ++++ openssl-0.9.8h/util/ssleay.num 2008-05-28 18:49:34.000000000 +0300 +@@ -241,3 +241,5 @@ SSL_CTX_sess_get_remove_cb + SSL_set_SSL_CTX 290 EXIST::FUNCTION: + SSL_get_servername 291 EXIST::FUNCTION:TLSEXT + SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT ++SSL_set_hello_extension 305 EXIST::FUNCTION:TLSEXT ++SSL_set_session_secret_cb 306 EXIST::FUNCTION:TLSEXT diff --git a/contrib/wpa/patches/openssl-0.9.8i-tls-extensions.patch b/contrib/wpa/patches/openssl-0.9.8i-tls-extensions.patch new file mode 100644 index 000000000000..90bff544eb59 --- /dev/null +++ b/contrib/wpa/patches/openssl-0.9.8i-tls-extensions.patch @@ -0,0 +1,404 @@ +This patch adds support for TLS SessionTicket extension (RFC 5077) for +the parts used by EAP-FAST (RFC 4851). + +This is based on the patch from Alexey Kobozev +(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). + +OpenSSL 0.9.8i does not enable TLS extension support by default, so it +will need to be enabled by adding enable-tlsext to config script +command line. + + +Index: openssl-0.9.8i/ssl/s3_clnt.c +=================================================================== +--- openssl-0.9.8i.orig/ssl/s3_clnt.c 2008-06-16 19:56:41.000000000 +0300 ++++ openssl-0.9.8i/ssl/s3_clnt.c 2008-11-23 20:39:40.000000000 +0200 +@@ -759,6 +759,21 @@ + goto f_err; + } + ++#ifndef OPENSSL_NO_TLSEXT ++ /* check if we want to resume the session based on external pre-shared secret */ ++ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if (s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, ++ NULL, &pref_cipher, s->tls_session_secret_cb_arg)) ++ { ++ s->session->cipher=pref_cipher ? ++ pref_cipher : ssl_get_cipher_by_char(s,p+j); ++ } ++ } ++#endif /* OPENSSL_NO_TLSEXT */ ++ + if (j != 0 && j == s->session->session_id_length + && memcmp(p,s->session->session_id,j) == 0) + { +@@ -2701,11 +2716,8 @@ + { + int ok; + long n; +- /* If we have no ticket or session ID is non-zero length (a match of +- * a non-zero session length would never reach here) it cannot be a +- * resumed session. +- */ +- if (!s->session->tlsext_tick || s->session->session_id_length) ++ /* If we have no ticket it cannot be a resumed session. */ ++ if (!s->session->tlsext_tick) + return 1; + /* this function is called when we really expect a Certificate + * message, so permit appropriate message length */ +Index: openssl-0.9.8i/ssl/s3_srvr.c +=================================================================== +--- openssl-0.9.8i.orig/ssl/s3_srvr.c 2008-09-14 21:16:09.000000000 +0300 ++++ openssl-0.9.8i/ssl/s3_srvr.c 2008-11-23 20:37:40.000000000 +0200 +@@ -959,6 +959,59 @@ + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); + goto err; + } ++ ++ /* Check if we want to use external pre-shared secret for this ++ * handshake for not reused session only. We need to generate ++ * server_random before calling tls_session_secret_cb in order to allow ++ * SessionTicket processing to use it in key derivation. */ ++ { ++ unsigned long Time; ++ unsigned char *pos; ++ Time=(unsigned long)time(NULL); /* Time */ ++ pos=s->s3->server_random; ++ l2n(Time,pos); ++ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0) ++ { ++ al=SSL_AD_INTERNAL_ERROR; ++ goto f_err; ++ } ++ } ++ ++ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, ++ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) ++ { ++ s->hit=1; ++ s->session->ciphers=ciphers; ++ s->session->verify_result=X509_V_OK; ++ ++ ciphers=NULL; ++ ++ /* check if some cipher was preferred by call back */ ++ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); ++ if (pref_cipher == NULL) ++ { ++ al=SSL_AD_HANDSHAKE_FAILURE; ++ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); ++ goto f_err; ++ } ++ ++ s->session->cipher=pref_cipher; ++ ++ if (s->cipher_list) ++ sk_SSL_CIPHER_free(s->cipher_list); ++ ++ if (s->cipher_list_by_id) ++ sk_SSL_CIPHER_free(s->cipher_list_by_id); ++ ++ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); ++ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); ++ } ++ } + #endif + /* Worst case, we will use the NULL compression, but if we have other + * options, we will now look for them. We have i-1 compression +@@ -1097,16 +1150,22 @@ + unsigned char *buf; + unsigned char *p,*d; + int i,sl; +- unsigned long l,Time; ++ unsigned long l; ++#ifdef OPENSSL_NO_TLSEXT ++ unsigned long Time; ++#endif + + if (s->state == SSL3_ST_SW_SRVR_HELLO_A) + { + buf=(unsigned char *)s->init_buf->data; ++#ifdef OPENSSL_NO_TLSEXT + p=s->s3->server_random; ++ /* Generate server_random if it was not needed previously */ + Time=(unsigned long)time(NULL); /* Time */ + l2n(Time,p); + if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) + return -1; ++#endif + /* Do the message type and length last */ + d=p= &(buf[4]); + +Index: openssl-0.9.8i/ssl/ssl_err.c +=================================================================== +--- openssl-0.9.8i.orig/ssl/ssl_err.c 2008-08-13 22:44:44.000000000 +0300 ++++ openssl-0.9.8i/ssl/ssl_err.c 2008-11-23 20:33:43.000000000 +0200 +@@ -253,6 +253,7 @@ + {ERR_FUNC(SSL_F_TLS1_ENC), "TLS1_ENC"}, + {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, + {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, ++{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"}, + {0,NULL} + }; + +Index: openssl-0.9.8i/ssl/ssl.h +=================================================================== +--- openssl-0.9.8i.orig/ssl/ssl.h 2008-08-13 22:44:44.000000000 +0300 ++++ openssl-0.9.8i/ssl/ssl.h 2008-11-23 20:35:41.000000000 +0200 +@@ -344,6 +344,7 @@ + * 'struct ssl_st *' function parameters used to prototype callbacks + * in SSL_CTX. */ + typedef struct ssl_st *ssl_crock_st; ++typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT; + + /* used to hold info on the particular ciphers used */ + typedef struct ssl_cipher_st +@@ -362,6 +363,9 @@ + + DECLARE_STACK_OF(SSL_CIPHER) + ++typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data, int len, void *arg); ++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); ++ + /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ + typedef struct ssl_method_st + { +@@ -1034,6 +1038,18 @@ + + /* RFC4507 session ticket expected to be received or sent */ + int tlsext_ticket_expected; ++ ++ /* TLS Session Ticket extension override */ ++ TLS_SESSION_TICKET_EXT *tlsext_session_ticket; ++ ++ /* TLS Session Ticket extension callback */ ++ tls_session_ticket_ext_cb_fn tls_session_ticket_ext_cb; ++ void *tls_session_ticket_ext_cb_arg; ++ ++ /* TLS pre-shared secret session resumption */ ++ tls_session_secret_cb_fn tls_session_secret_cb; ++ void *tls_session_secret_cb_arg; ++ + SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ + #define session_ctx initial_ctx + #else +@@ -1632,6 +1648,15 @@ + int SSL_COMP_add_compression_method(int id,void *cm); + #endif + ++/* TLS extensions functions */ ++int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len); ++ ++int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, ++ void *arg); ++ ++/* Pre-shared secret session resumption functions */ ++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); ++ + /* BEGIN ERROR CODES */ + /* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. +@@ -1824,6 +1849,7 @@ + #define SSL_F_TLS1_ENC 210 + #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 + #define SSL_F_WRITE_PENDING 212 ++#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213 + + /* Reason codes. */ + #define SSL_R_APP_DATA_IN_HANDSHAKE 100 +Index: openssl-0.9.8i/ssl/ssl_sess.c +=================================================================== +--- openssl-0.9.8i.orig/ssl/ssl_sess.c 2008-06-04 21:35:27.000000000 +0300 ++++ openssl-0.9.8i/ssl/ssl_sess.c 2008-11-23 20:32:24.000000000 +0200 +@@ -707,6 +707,61 @@ + return(s->session_timeout); + } + ++#ifndef OPENSSL_NO_TLSEXT ++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, ++ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) ++ { ++ if (s == NULL) return(0); ++ s->tls_session_secret_cb = tls_session_secret_cb; ++ s->tls_session_secret_cb_arg = arg; ++ return(1); ++ } ++ ++int SSL_set_session_ticket_ext_cb(SSL *s, tls_session_ticket_ext_cb_fn cb, ++ void *arg) ++ { ++ if (s == NULL) return(0); ++ s->tls_session_ticket_ext_cb = cb; ++ s->tls_session_ticket_ext_cb_arg = arg; ++ return(1); ++ } ++ ++int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) ++ { ++ if (s->version >= TLS1_VERSION) ++ { ++ if (s->tlsext_session_ticket) ++ { ++ OPENSSL_free(s->tlsext_session_ticket); ++ s->tlsext_session_ticket = NULL; ++ } ++ ++ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len); ++ if (!s->tlsext_session_ticket) ++ { ++ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ ++ if (ext_data) ++ { ++ s->tlsext_session_ticket->length = ext_len; ++ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1; ++ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len); ++ } ++ else ++ { ++ s->tlsext_session_ticket->length = 0; ++ s->tlsext_session_ticket->data = NULL; ++ } ++ ++ return 1; ++ } ++ ++ return 0; ++ } ++#endif /* OPENSSL_NO_TLSEXT */ ++ + typedef struct timeout_param_st + { + SSL_CTX *ctx; +Index: openssl-0.9.8i/ssl/t1_lib.c +=================================================================== +--- openssl-0.9.8i.orig/ssl/t1_lib.c 2008-09-04 01:13:04.000000000 +0300 ++++ openssl-0.9.8i/ssl/t1_lib.c 2008-11-23 20:31:20.000000000 +0200 +@@ -106,6 +106,12 @@ + + void tls1_free(SSL *s) + { ++#ifndef OPENSSL_NO_TLSEXT ++ if (s->tlsext_session_ticket) ++ { ++ OPENSSL_free(s->tlsext_session_ticket); ++ } ++#endif + ssl3_free(s); + } + +@@ -175,8 +181,23 @@ + int ticklen; + if (s->session && s->session->tlsext_tick) + ticklen = s->session->tlsext_ticklen; ++ else if (s->session && s->tlsext_session_ticket && ++ s->tlsext_session_ticket->data) ++ { ++ ticklen = s->tlsext_session_ticket->length; ++ s->session->tlsext_tick = OPENSSL_malloc(ticklen); ++ if (!s->session->tlsext_tick) ++ return NULL; ++ memcpy(s->session->tlsext_tick, ++ s->tlsext_session_ticket->data, ++ ticklen); ++ s->session->tlsext_ticklen = ticklen; ++ } + else + ticklen = 0; ++ if (ticklen == 0 && s->tlsext_session_ticket && ++ s->tlsext_session_ticket->data == NULL) ++ goto skip_ext; + /* Check for enough room 2 for extension type, 2 for len + * rest for ticket + */ +@@ -190,6 +211,7 @@ + ret += ticklen; + } + } ++ skip_ext: + + if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) + { +@@ -407,6 +429,15 @@ + } + + } ++ else if (type == TLSEXT_TYPE_session_ticket) ++ { ++ if (s->tls_session_ticket_ext_cb && ++ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg)) ++ { ++ *al = TLS1_AD_INTERNAL_ERROR; ++ return 0; ++ } ++ } + else if (type == TLSEXT_TYPE_status_request + && s->ctx->tlsext_status_cb) + { +@@ -553,6 +584,12 @@ + } + else if (type == TLSEXT_TYPE_session_ticket) + { ++ if (s->tls_session_ticket_ext_cb && ++ !s->tls_session_ticket_ext_cb(s, data, size, s->tls_session_ticket_ext_cb_arg)) ++ { ++ *al = TLS1_AD_INTERNAL_ERROR; ++ return 0; ++ } + if ((SSL_get_options(s) & SSL_OP_NO_TICKET) + || (size > 0)) + { +@@ -776,6 +813,15 @@ + s->tlsext_ticket_expected = 1; + return 0; /* Cache miss */ + } ++ if (s->tls_session_secret_cb) ++ { ++ /* Indicate cache miss here and instead of ++ * generating the session from ticket now, ++ * trigger abbreviated handshake based on ++ * external mechanism to calculate the master ++ * secret later. */ ++ return 0; ++ } + return tls_decrypt_ticket(s, p, size, session_id, len, + ret); + } +Index: openssl-0.9.8i/ssl/tls1.h +=================================================================== +--- openssl-0.9.8i.orig/ssl/tls1.h 2008-04-30 19:11:33.000000000 +0300 ++++ openssl-0.9.8i/ssl/tls1.h 2008-11-23 20:22:38.000000000 +0200 +@@ -398,6 +398,13 @@ + #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ + #endif + ++/* TLS extension struct */ ++struct tls_session_ticket_ext_st ++ { ++ unsigned short length; ++ void *data; ++ }; ++ + #ifdef __cplusplus + } + #endif +Index: openssl-0.9.8i/util/ssleay.num +=================================================================== +--- openssl-0.9.8i.orig/util/ssleay.num 2008-06-05 13:57:21.000000000 +0300 ++++ openssl-0.9.8i/util/ssleay.num 2008-11-23 20:22:05.000000000 +0200 +@@ -242,3 +242,5 @@ + SSL_get_servername 291 EXIST::FUNCTION:TLSEXT + SSL_get_servername_type 292 EXIST::FUNCTION:TLSEXT + SSL_CTX_set_client_cert_engine 293 EXIST::FUNCTION:ENGINE ++SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT ++SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT diff --git a/contrib/wpa/patches/openssl-0.9.9-session-ticket.patch b/contrib/wpa/patches/openssl-0.9.9-session-ticket.patch new file mode 100644 index 000000000000..3afa639ad898 --- /dev/null +++ b/contrib/wpa/patches/openssl-0.9.9-session-ticket.patch @@ -0,0 +1,374 @@ +This patch adds support for TLS SessionTicket extension (RFC 5077) for +the parts used by EAP-FAST (RFC 4851). + +This is based on the patch from Alexey Kobozev +(sent to openssl-dev mailing list on Tue, 07 Jun 2005 15:40:58 +0300). + +NOTE: This patch (without SSL_set_hello_extension() wrapper) was +merged into the upstream OpenSSL 0.9.9 tree and as such, an external +patch for EAP-FAST support is not needed anymore. + + + +Index: openssl-SNAP-20081111/ssl/s3_clnt.c +=================================================================== +--- openssl-SNAP-20081111.orig/ssl/s3_clnt.c ++++ openssl-SNAP-20081111/ssl/s3_clnt.c +@@ -788,6 +788,23 @@ int ssl3_get_server_hello(SSL *s) + goto f_err; + } + ++#ifndef OPENSSL_NO_TLSEXT ++ /* check if we want to resume the session based on external pre-shared secret */ ++ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if (s->tls_session_secret_cb(s, s->session->master_key, ++ &s->session->master_key_length, ++ NULL, &pref_cipher, ++ s->tls_session_secret_cb_arg)) ++ { ++ s->session->cipher = pref_cipher ? ++ pref_cipher : ssl_get_cipher_by_char(s, p+j); ++ } ++ } ++#endif /* OPENSSL_NO_TLSEXT */ ++ + if (j != 0 && j == s->session->session_id_length + && memcmp(p,s->session->session_id,j) == 0) + { +@@ -2927,11 +2944,8 @@ static int ssl3_check_finished(SSL *s) + { + int ok; + long n; +- /* If we have no ticket or session ID is non-zero length (a match of +- * a non-zero session length would never reach here) it cannot be a +- * resumed session. +- */ +- if (!s->session->tlsext_tick || s->session->session_id_length) ++ /* If we have no ticket it cannot be a resumed session. */ ++ if (!s->session->tlsext_tick) + return 1; + /* this function is called when we really expect a Certificate + * message, so permit appropriate message length */ +Index: openssl-SNAP-20081111/ssl/s3_srvr.c +=================================================================== +--- openssl-SNAP-20081111.orig/ssl/s3_srvr.c ++++ openssl-SNAP-20081111/ssl/s3_srvr.c +@@ -1010,6 +1010,59 @@ int ssl3_get_client_hello(SSL *s) + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); + goto err; + } ++ ++ /* Check if we want to use external pre-shared secret for this ++ * handshake for not reused session only. We need to generate ++ * server_random before calling tls_session_secret_cb in order to allow ++ * SessionTicket processing to use it in key derivation. */ ++ { ++ unsigned long Time; ++ unsigned char *pos; ++ Time=(unsigned long)time(NULL); /* Time */ ++ pos=s->s3->server_random; ++ l2n(Time,pos); ++ if (RAND_pseudo_bytes(pos,SSL3_RANDOM_SIZE-4) <= 0) ++ { ++ al=SSL_AD_INTERNAL_ERROR; ++ goto f_err; ++ } ++ } ++ ++ if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) ++ { ++ SSL_CIPHER *pref_cipher=NULL; ++ ++ s->session->master_key_length=sizeof(s->session->master_key); ++ if(s->tls_session_secret_cb(s, s->session->master_key, &s->session->master_key_length, ++ ciphers, &pref_cipher, s->tls_session_secret_cb_arg)) ++ { ++ s->hit=1; ++ s->session->ciphers=ciphers; ++ s->session->verify_result=X509_V_OK; ++ ++ ciphers=NULL; ++ ++ /* check if some cipher was preferred by call back */ ++ pref_cipher=pref_cipher ? pref_cipher : ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s)); ++ if (pref_cipher == NULL) ++ { ++ al=SSL_AD_HANDSHAKE_FAILURE; ++ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_NO_SHARED_CIPHER); ++ goto f_err; ++ } ++ ++ s->session->cipher=pref_cipher; ++ ++ if (s->cipher_list) ++ sk_SSL_CIPHER_free(s->cipher_list); ++ ++ if (s->cipher_list_by_id) ++ sk_SSL_CIPHER_free(s->cipher_list_by_id); ++ ++ s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers); ++ s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); ++ } ++ } + #endif + + /* Worst case, we will use the NULL compression, but if we have other +@@ -1134,16 +1187,22 @@ int ssl3_send_server_hello(SSL *s) + unsigned char *buf; + unsigned char *p,*d; + int i,sl; +- unsigned long l,Time; ++ unsigned long l; ++#ifdef OPENSSL_NO_TLSEXT ++ unsigned long Time; ++#endif + + if (s->state == SSL3_ST_SW_SRVR_HELLO_A) + { + buf=(unsigned char *)s->init_buf->data; ++#ifdef OPENSSL_NO_TLSEXT + p=s->s3->server_random; ++ /* Generate server_random if it was not needed previously */ + Time=(unsigned long)time(NULL); /* Time */ + l2n(Time,p); + if (RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4) <= 0) + return -1; ++#endif + /* Do the message type and length last */ + d=p= &(buf[4]); + +Index: openssl-SNAP-20081111/ssl/ssl_err.c +=================================================================== +--- openssl-SNAP-20081111.orig/ssl/ssl_err.c ++++ openssl-SNAP-20081111/ssl/ssl_err.c +@@ -263,6 +263,7 @@ static ERR_STRING_DATA SSL_str_functs[]= + {ERR_FUNC(SSL_F_TLS1_PRF), "tls1_prf"}, + {ERR_FUNC(SSL_F_TLS1_SETUP_KEY_BLOCK), "TLS1_SETUP_KEY_BLOCK"}, + {ERR_FUNC(SSL_F_WRITE_PENDING), "WRITE_PENDING"}, ++{ERR_FUNC(SSL_F_SSL_SET_SESSION_TICKET_EXT), "SSL_set_session_ticket_ext"}, + {0,NULL} + }; + +Index: openssl-SNAP-20081111/ssl/ssl.h +=================================================================== +--- openssl-SNAP-20081111.orig/ssl/ssl.h ++++ openssl-SNAP-20081111/ssl/ssl.h +@@ -355,6 +355,7 @@ extern "C" { + * 'struct ssl_st *' function parameters used to prototype callbacks + * in SSL_CTX. */ + typedef struct ssl_st *ssl_crock_st; ++typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT; + + /* used to hold info on the particular ciphers used */ + typedef struct ssl_cipher_st +@@ -378,6 +379,8 @@ typedef struct ssl_cipher_st + + DECLARE_STACK_OF(SSL_CIPHER) + ++typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len, STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg); ++ + /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */ + typedef struct ssl_method_st + { +@@ -1145,6 +1148,13 @@ struct ssl_st + void *tlsext_opaque_prf_input; + size_t tlsext_opaque_prf_input_len; + ++ /* TLS Session Ticket extension override */ ++ TLS_SESSION_TICKET_EXT *tlsext_session_ticket; ++ ++ /* TLS pre-shared secret session resumption */ ++ tls_session_secret_cb_fn tls_session_secret_cb; ++ void *tls_session_secret_cb_arg; ++ + SSL_CTX * initial_ctx; /* initial ctx, used to store sessions */ + #define session_ctx initial_ctx + #else +@@ -1746,6 +1756,16 @@ void *SSL_COMP_get_compression_methods(v + int SSL_COMP_add_compression_method(int id,void *cm); + #endif + ++/* NOTE: This function will be removed; it is only here for backwards ++ * compatibility for the API during testing. */ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len); ++ ++/* TLS extensions functions */ ++int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len); ++ ++/* Pre-shared secret session resumption functions */ ++int SSL_set_session_secret_cb(SSL *s, tls_session_secret_cb_fn tls_session_secret_cb, void *arg); ++ + /* BEGIN ERROR CODES */ + /* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. +@@ -1948,6 +1968,7 @@ void ERR_load_SSL_strings(void); + #define SSL_F_TLS1_PRF 284 + #define SSL_F_TLS1_SETUP_KEY_BLOCK 211 + #define SSL_F_WRITE_PENDING 212 ++#define SSL_F_SSL_SET_SESSION_TICKET_EXT 213 + + /* Reason codes. */ + #define SSL_R_APP_DATA_IN_HANDSHAKE 100 +Index: openssl-SNAP-20081111/ssl/ssl_sess.c +=================================================================== +--- openssl-SNAP-20081111.orig/ssl/ssl_sess.c ++++ openssl-SNAP-20081111/ssl/ssl_sess.c +@@ -834,6 +834,62 @@ long SSL_CTX_get_timeout(const SSL_CTX * + return(s->session_timeout); + } + ++#ifndef OPENSSL_NO_TLSEXT ++int SSL_set_session_secret_cb(SSL *s, int (*tls_session_secret_cb)(SSL *s, void *secret, int *secret_len, ++ STACK_OF(SSL_CIPHER) *peer_ciphers, SSL_CIPHER **cipher, void *arg), void *arg) ++ { ++ if (s == NULL) return(0); ++ s->tls_session_secret_cb = tls_session_secret_cb; ++ s->tls_session_secret_cb_arg = arg; ++ return(1); ++ } ++ ++int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) ++ { ++ if (s->version >= TLS1_VERSION) ++ { ++ if (s->tlsext_session_ticket) ++ { ++ OPENSSL_free(s->tlsext_session_ticket); ++ s->tlsext_session_ticket = NULL; ++ } ++ ++ s->tlsext_session_ticket = OPENSSL_malloc(sizeof(TLS_SESSION_TICKET_EXT) + ext_len); ++ if (!s->tlsext_session_ticket) ++ { ++ SSLerr(SSL_F_SSL_SET_SESSION_TICKET_EXT, ERR_R_MALLOC_FAILURE); ++ return 0; ++ } ++ ++ if (ext_data) ++ { ++ s->tlsext_session_ticket->length = ext_len; ++ s->tlsext_session_ticket->data = s->tlsext_session_ticket + 1; ++ memcpy(s->tlsext_session_ticket->data, ext_data, ext_len); ++ } ++ else ++ { ++ s->tlsext_session_ticket->length = 0; ++ s->tlsext_session_ticket->data = NULL; ++ } ++ ++ return 1; ++ } ++ ++ return 0; ++ } ++ ++/* NOTE: This function will be removed; it is only here for backwards ++ * compatibility for the API during testing. */ ++int SSL_set_hello_extension(SSL *s, int ext_type, void *ext_data, int ext_len) ++ { ++ if (ext_type != TLSEXT_TYPE_session_ticket) ++ return 0; ++ ++ return SSL_set_session_ticket_ext(s, ext_data, ext_len); ++ } ++#endif /* OPENSSL_NO_TLSEXT */ ++ + typedef struct timeout_param_st + { + SSL_CTX *ctx; +Index: openssl-SNAP-20081111/ssl/t1_lib.c +=================================================================== +--- openssl-SNAP-20081111.orig/ssl/t1_lib.c ++++ openssl-SNAP-20081111/ssl/t1_lib.c +@@ -154,6 +154,12 @@ int tls1_new(SSL *s) + + void tls1_free(SSL *s) + { ++#ifndef OPENSSL_NO_TLSEXT ++ if (s->tlsext_session_ticket) ++ { ++ OPENSSL_free(s->tlsext_session_ticket); ++ } ++#endif /* OPENSSL_NO_TLSEXT */ + ssl3_free(s); + } + +@@ -357,8 +363,23 @@ unsigned char *ssl_add_clienthello_tlsex + int ticklen; + if (s->session && s->session->tlsext_tick) + ticklen = s->session->tlsext_ticklen; ++ else if (s->session && s->tlsext_session_ticket && ++ s->tlsext_session_ticket->data) ++ { ++ ticklen = s->tlsext_session_ticket->length; ++ s->session->tlsext_tick = OPENSSL_malloc(ticklen); ++ if (!s->session->tlsext_tick) ++ return NULL; ++ memcpy(s->session->tlsext_tick, ++ s->tlsext_session_ticket->data, ++ ticklen); ++ s->session->tlsext_ticklen = ticklen; ++ } + else + ticklen = 0; ++ if (ticklen == 0 && s->tlsext_session_ticket && ++ s->tlsext_session_ticket->data == NULL) ++ goto skip_ext; + /* Check for enough room 2 for extension type, 2 for len + * rest for ticket + */ +@@ -371,6 +392,7 @@ unsigned char *ssl_add_clienthello_tlsex + ret += ticklen; + } + } ++ skip_ext: + + #ifdef TLSEXT_TYPE_opaque_prf_input + if (s->s3->client_opaque_prf_input != NULL) +@@ -1435,6 +1457,15 @@ int tls1_process_ticket(SSL *s, unsigned + s->tlsext_ticket_expected = 1; + return 0; /* Cache miss */ + } ++ if (s->tls_session_secret_cb) ++ { ++ /* Indicate cache miss here and instead of ++ * generating the session from ticket now, ++ * trigger abbreviated handshake based on ++ * external mechanism to calculate the master ++ * secret later. */ ++ return 0; ++ } + return tls_decrypt_ticket(s, p, size, session_id, len, + ret); + } +Index: openssl-SNAP-20081111/ssl/tls1.h +=================================================================== +--- openssl-SNAP-20081111.orig/ssl/tls1.h ++++ openssl-SNAP-20081111/ssl/tls1.h +@@ -512,6 +512,13 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_T + #define TLS_MD_MASTER_SECRET_CONST "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74" /*master secret*/ + #endif + ++/* TLS Session Ticket extension struct */ ++struct tls_session_ticket_ext_st ++ { ++ unsigned short length; ++ void *data; ++ }; ++ + #ifdef __cplusplus + } + #endif +Index: openssl-SNAP-20081111/util/ssleay.num +=================================================================== +--- openssl-SNAP-20081111.orig/util/ssleay.num ++++ openssl-SNAP-20081111/util/ssleay.num +@@ -254,3 +254,5 @@ PEM_read_bio_SSL_SESSION + SSL_CTX_set_psk_server_callback 303 EXIST::FUNCTION:PSK + SSL_get_psk_identity 304 EXIST::FUNCTION:PSK + PEM_write_SSL_SESSION 305 EXIST:!WIN16:FUNCTION: ++SSL_set_session_ticket_ext 306 EXIST::FUNCTION:TLSEXT ++SSL_set_session_secret_cb 307 EXIST::FUNCTION:TLSEXT diff --git a/contrib/wpa/src/Makefile b/contrib/wpa/src/Makefile index bd1c160cd514..f47da7b5ac73 100644 --- a/contrib/wpa/src/Makefile +++ b/contrib/wpa/src/Makefile @@ -1,7 +1,7 @@ -SUBDIRS=common crypto drivers hlr_auc_gw eapol_supp eap_common eap_peer eap_server l2_packet radius rsn_supp tls utils wps +SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet radius rsn_supp tls utils wps all: - @echo Nothing to be made. + for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done clean: for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done diff --git a/contrib/wpa/src/hlr_auc_gw/Makefile b/contrib/wpa/src/ap/Makefile similarity index 65% rename from contrib/wpa/src/hlr_auc_gw/Makefile rename to contrib/wpa/src/ap/Makefile index cffba620da04..9c41962fd7e1 100644 --- a/contrib/wpa/src/hlr_auc_gw/Makefile +++ b/contrib/wpa/src/ap/Makefile @@ -2,7 +2,6 @@ all: @echo Nothing to be made. clean: - for d in $(SUBDIRS); do make -C $$d clean; done rm -f *~ *.o *.d install: diff --git a/contrib/wpa/hostapd/accounting.c b/contrib/wpa/src/ap/accounting.c similarity index 96% rename from contrib/wpa/hostapd/accounting.c rename to contrib/wpa/src/ap/accounting.c index ce71678af4e9..7939c680f580 100644 --- a/contrib/wpa/hostapd/accounting.c +++ b/contrib/wpa/src/ap/accounting.c @@ -1,6 +1,6 @@ /* * hostapd / RADIUS Accounting - * Copyright (c) 2002-2008, Jouni Malinen + * Copyright (c) 2002-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,15 +12,18 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" -#include "hostapd.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "drivers/driver.h" #include "radius/radius.h" #include "radius/radius_client.h" -#include "eloop.h" -#include "accounting.h" +#include "hostapd.h" #include "ieee802_1x.h" -#include "driver.h" +#include "ap_config.h" +#include "sta_info.h" +#include "accounting.h" /* Default interval in seconds for polling TX/RX octets from the driver if @@ -175,7 +178,6 @@ static struct radius_msg * accounting_msg(struct hostapd_data *hapd, fail: radius_msg_free(msg); - os_free(msg); return NULL; } @@ -184,7 +186,7 @@ static int accounting_sta_update_stats(struct hostapd_data *hapd, struct sta_info *sta, struct hostap_sta_driver_data *data) { - if (hostapd_read_sta_data(hapd, data, sta->addr)) + if (hapd->drv.read_sta_data(hapd, data, sta->addr)) return -1; if (sta->last_rx_bytes > data->rx_bytes) @@ -247,7 +249,7 @@ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta) time(&sta->acct_session_start); sta->last_rx_bytes = sta->last_tx_bytes = 0; sta->acct_input_gigawords = sta->acct_output_gigawords = 0; - hostapd_sta_clear_stats(hapd, sta->addr); + hapd->drv.sta_clear_stats(hapd, sta->addr); if (!hapd->conf->radius->acct_server) return; @@ -364,7 +366,6 @@ static void accounting_sta_report(struct hostapd_data *hapd, fail: radius_msg_free(msg); - os_free(msg); } @@ -425,7 +426,7 @@ accounting_receive(struct radius_msg *msg, struct radius_msg *req, const u8 *shared_secret, size_t shared_secret_len, void *data) { - if (msg->hdr->code != RADIUS_CODE_ACCOUNTING_RESPONSE) { + if (radius_msg_get_hdr(msg)->code != RADIUS_CODE_ACCOUNTING_RESPONSE) { printf("Unknown RADIUS message code\n"); return RADIUS_RX_UNKNOWN; } @@ -460,7 +461,6 @@ static void accounting_report_state(struct hostapd_data *hapd, int on) { printf("Could not add Acct-Terminate-Cause\n"); radius_msg_free(msg); - os_free(msg); return; } @@ -497,14 +497,3 @@ void accounting_deinit(struct hostapd_data *hapd) { accounting_report_state(hapd, 0); } - - -int accounting_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf) -{ - if (!hapd->radius_client_reconfigured) - return 0; - - accounting_deinit(hapd); - return accounting_init(hapd); -} diff --git a/contrib/wpa/hostapd/accounting.h b/contrib/wpa/src/ap/accounting.h similarity index 64% rename from contrib/wpa/hostapd/accounting.h rename to contrib/wpa/src/ap/accounting.h index 51e6b4d49870..f3d60f0155a6 100644 --- a/contrib/wpa/hostapd/accounting.h +++ b/contrib/wpa/src/ap/accounting.h @@ -15,12 +15,31 @@ #ifndef ACCOUNTING_H #define ACCOUNTING_H -void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta); void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta); +#ifdef CONFIG_NO_ACCOUNTING +static inline void accounting_sta_start(struct hostapd_data *hapd, + struct sta_info *sta) +{ +} + +static inline void accounting_sta_stop(struct hostapd_data *hapd, + struct sta_info *sta) +{ +} + +static inline int accounting_init(struct hostapd_data *hapd) +{ + return 0; +} + +static inline void accounting_deinit(struct hostapd_data *hapd) +{ +} +#else /* CONFIG_NO_ACCOUNTING */ +void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta); void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta); int accounting_init(struct hostapd_data *hapd); void accounting_deinit(struct hostapd_data *hapd); -int accounting_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf); +#endif /* CONFIG_NO_ACCOUNTING */ #endif /* ACCOUNTING_H */ diff --git a/contrib/wpa/src/ap/ap_config.c b/contrib/wpa/src/ap/ap_config.c new file mode 100644 index 000000000000..59969933e2f9 --- /dev/null +++ b/contrib/wpa/src/ap/ap_config.c @@ -0,0 +1,605 @@ +/* + * hostapd / Configuration helper functions + * Copyright (c) 2003-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "crypto/sha1.h" +#include "radius/radius_client.h" +#include "common/ieee802_11_defs.h" +#include "common/eapol_common.h" +#include "eap_common/eap_wsc_common.h" +#include "eap_server/eap.h" +#include "wpa_auth.h" +#include "sta_info.h" +#include "ap_config.h" + + +static void hostapd_config_free_vlan(struct hostapd_bss_config *bss) +{ + struct hostapd_vlan *vlan, *prev; + + vlan = bss->vlan; + prev = NULL; + while (vlan) { + prev = vlan; + vlan = vlan->next; + os_free(prev); + } + + bss->vlan = NULL; +} + + +void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) +{ + bss->logger_syslog_level = HOSTAPD_LEVEL_INFO; + bss->logger_stdout_level = HOSTAPD_LEVEL_INFO; + bss->logger_syslog = (unsigned int) -1; + bss->logger_stdout = (unsigned int) -1; + + bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED; + + bss->wep_rekeying_period = 300; + /* use key0 in individual key and key1 in broadcast key */ + bss->broadcast_key_idx_min = 1; + bss->broadcast_key_idx_max = 2; + bss->eap_reauth_period = 3600; + + bss->wpa_group_rekey = 600; + bss->wpa_gmk_rekey = 86400; + bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; + bss->wpa_pairwise = WPA_CIPHER_TKIP; + bss->wpa_group = WPA_CIPHER_TKIP; + bss->rsn_pairwise = 0; + + bss->max_num_sta = MAX_STA_COUNT; + + bss->dtim_period = 2; + + bss->radius_server_auth_port = 1812; + bss->ap_max_inactivity = AP_MAX_INACTIVITY; + bss->eapol_version = EAPOL_VERSION; + + bss->max_listen_interval = 65535; + +#ifdef CONFIG_IEEE80211W + bss->assoc_sa_query_max_timeout = 1000; + bss->assoc_sa_query_retry_timeout = 201; +#endif /* CONFIG_IEEE80211W */ +#ifdef EAP_SERVER_FAST + /* both anonymous and authenticated provisioning */ + bss->eap_fast_prov = 3; + bss->pac_key_lifetime = 7 * 24 * 60 * 60; + bss->pac_key_refresh_time = 1 * 24 * 60 * 60; +#endif /* EAP_SERVER_FAST */ +} + + +struct hostapd_config * hostapd_config_defaults(void) +{ + struct hostapd_config *conf; + struct hostapd_bss_config *bss; + int i; + const int aCWmin = 4, aCWmax = 10; + const struct hostapd_wmm_ac_params ac_bk = + { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */ + const struct hostapd_wmm_ac_params ac_be = + { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ + const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ + { aCWmin - 1, aCWmin, 2, 3000 / 32, 1 }; + const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ + { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 1 }; + + conf = os_zalloc(sizeof(*conf)); + bss = os_zalloc(sizeof(*bss)); + if (conf == NULL || bss == NULL) { + wpa_printf(MSG_ERROR, "Failed to allocate memory for " + "configuration data."); + os_free(conf); + os_free(bss); + return NULL; + } + + bss->radius = os_zalloc(sizeof(*bss->radius)); + if (bss->radius == NULL) { + os_free(conf); + os_free(bss); + return NULL; + } + + hostapd_config_defaults_bss(bss); + + conf->num_bss = 1; + conf->bss = bss; + + conf->beacon_int = 100; + conf->rts_threshold = -1; /* use driver default: 2347 */ + conf->fragm_threshold = -1; /* user driver default: 2346 */ + conf->send_probe_response = 1; + + for (i = 0; i < NUM_TX_QUEUES; i++) + conf->tx_queue[i].aifs = -1; /* use hw default */ + + conf->wmm_ac_params[0] = ac_be; + conf->wmm_ac_params[1] = ac_bk; + conf->wmm_ac_params[2] = ac_vi; + conf->wmm_ac_params[3] = ac_vo; + + conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED; + + return conf; +} + + +int hostapd_mac_comp(const void *a, const void *b) +{ + return os_memcmp(a, b, sizeof(macaddr)); +} + + +int hostapd_mac_comp_empty(const void *a) +{ + macaddr empty = { 0 }; + return os_memcmp(a, empty, sizeof(macaddr)); +} + + +static int hostapd_config_read_wpa_psk(const char *fname, + struct hostapd_ssid *ssid) +{ + FILE *f; + char buf[128], *pos; + int line = 0, ret = 0, len, ok; + u8 addr[ETH_ALEN]; + struct hostapd_wpa_psk *psk; + + if (!fname) + return 0; + + f = fopen(fname, "r"); + if (!f) { + wpa_printf(MSG_ERROR, "WPA PSK file '%s' not found.", fname); + return -1; + } + + while (fgets(buf, sizeof(buf), f)) { + line++; + + if (buf[0] == '#') + continue; + pos = buf; + while (*pos != '\0') { + if (*pos == '\n') { + *pos = '\0'; + break; + } + pos++; + } + if (buf[0] == '\0') + continue; + + if (hwaddr_aton(buf, addr)) { + wpa_printf(MSG_ERROR, "Invalid MAC address '%s' on " + "line %d in '%s'", buf, line, fname); + ret = -1; + break; + } + + psk = os_zalloc(sizeof(*psk)); + if (psk == NULL) { + wpa_printf(MSG_ERROR, "WPA PSK allocation failed"); + ret = -1; + break; + } + if (is_zero_ether_addr(addr)) + psk->group = 1; + else + os_memcpy(psk->addr, addr, ETH_ALEN); + + pos = buf + 17; + if (*pos == '\0') { + wpa_printf(MSG_ERROR, "No PSK on line %d in '%s'", + line, fname); + os_free(psk); + ret = -1; + break; + } + pos++; + + ok = 0; + len = os_strlen(pos); + if (len == 64 && hexstr2bin(pos, psk->psk, PMK_LEN) == 0) + ok = 1; + else if (len >= 8 && len < 64) { + pbkdf2_sha1(pos, ssid->ssid, ssid->ssid_len, + 4096, psk->psk, PMK_LEN); + ok = 1; + } + if (!ok) { + wpa_printf(MSG_ERROR, "Invalid PSK '%s' on line %d in " + "'%s'", pos, line, fname); + os_free(psk); + ret = -1; + break; + } + + psk->next = ssid->wpa_psk; + ssid->wpa_psk = psk; + } + + fclose(f); + + return ret; +} + + +static int hostapd_derive_psk(struct hostapd_ssid *ssid) +{ + ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); + if (ssid->wpa_psk == NULL) { + wpa_printf(MSG_ERROR, "Unable to alloc space for PSK"); + return -1; + } + wpa_hexdump_ascii(MSG_DEBUG, "SSID", + (u8 *) ssid->ssid, ssid->ssid_len); + wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)", + (u8 *) ssid->wpa_passphrase, + os_strlen(ssid->wpa_passphrase)); + pbkdf2_sha1(ssid->wpa_passphrase, + ssid->ssid, ssid->ssid_len, + 4096, ssid->wpa_psk->psk, PMK_LEN); + wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)", + ssid->wpa_psk->psk, PMK_LEN); + return 0; +} + + +int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf) +{ + struct hostapd_ssid *ssid = &conf->ssid; + + if (ssid->wpa_passphrase != NULL) { + if (ssid->wpa_psk != NULL) { + wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK " + "instead of passphrase"); + } else { + wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on " + "passphrase"); + if (hostapd_derive_psk(ssid) < 0) + return -1; + } + ssid->wpa_psk->group = 1; + } + + if (ssid->wpa_psk_file) { + if (hostapd_config_read_wpa_psk(ssid->wpa_psk_file, + &conf->ssid)) + return -1; + } + + return 0; +} + + +int hostapd_wep_key_cmp(struct hostapd_wep_keys *a, struct hostapd_wep_keys *b) +{ + int i; + + if (a->idx != b->idx || a->default_len != b->default_len) + return 1; + for (i = 0; i < NUM_WEP_KEYS; i++) + if (a->len[i] != b->len[i] || + os_memcmp(a->key[i], b->key[i], a->len[i]) != 0) + return 1; + return 0; +} + + +static void hostapd_config_free_radius(struct hostapd_radius_server *servers, + int num_servers) +{ + int i; + + for (i = 0; i < num_servers; i++) { + os_free(servers[i].shared_secret); + } + os_free(servers); +} + + +static void hostapd_config_free_eap_user(struct hostapd_eap_user *user) +{ + os_free(user->identity); + os_free(user->password); + os_free(user); +} + + +static void hostapd_config_free_wep(struct hostapd_wep_keys *keys) +{ + int i; + for (i = 0; i < NUM_WEP_KEYS; i++) { + os_free(keys->key[i]); + keys->key[i] = NULL; + } +} + + +static void hostapd_config_free_bss(struct hostapd_bss_config *conf) +{ + struct hostapd_wpa_psk *psk, *prev; + struct hostapd_eap_user *user, *prev_user; + + if (conf == NULL) + return; + + psk = conf->ssid.wpa_psk; + while (psk) { + prev = psk; + psk = psk->next; + os_free(prev); + } + + os_free(conf->ssid.wpa_passphrase); + os_free(conf->ssid.wpa_psk_file); + hostapd_config_free_wep(&conf->ssid.wep); +#ifdef CONFIG_FULL_DYNAMIC_VLAN + os_free(conf->ssid.vlan_tagged_interface); +#endif /* CONFIG_FULL_DYNAMIC_VLAN */ + + user = conf->eap_user; + while (user) { + prev_user = user; + user = user->next; + hostapd_config_free_eap_user(prev_user); + } + + os_free(conf->dump_log_name); + os_free(conf->eap_req_id_text); + os_free(conf->accept_mac); + os_free(conf->deny_mac); + os_free(conf->nas_identifier); + hostapd_config_free_radius(conf->radius->auth_servers, + conf->radius->num_auth_servers); + hostapd_config_free_radius(conf->radius->acct_servers, + conf->radius->num_acct_servers); + os_free(conf->rsn_preauth_interfaces); + os_free(conf->ctrl_interface); + os_free(conf->ca_cert); + os_free(conf->server_cert); + os_free(conf->private_key); + os_free(conf->private_key_passwd); + os_free(conf->dh_file); + os_free(conf->pac_opaque_encr_key); + os_free(conf->eap_fast_a_id); + os_free(conf->eap_fast_a_id_info); + os_free(conf->eap_sim_db); + os_free(conf->radius_server_clients); + os_free(conf->test_socket); + os_free(conf->radius); + hostapd_config_free_vlan(conf); + if (conf->ssid.dyn_vlan_keys) { + struct hostapd_ssid *ssid = &conf->ssid; + size_t i; + for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) { + if (ssid->dyn_vlan_keys[i] == NULL) + continue; + hostapd_config_free_wep(ssid->dyn_vlan_keys[i]); + os_free(ssid->dyn_vlan_keys[i]); + } + os_free(ssid->dyn_vlan_keys); + ssid->dyn_vlan_keys = NULL; + } + +#ifdef CONFIG_IEEE80211R + { + struct ft_remote_r0kh *r0kh, *r0kh_prev; + struct ft_remote_r1kh *r1kh, *r1kh_prev; + + r0kh = conf->r0kh_list; + conf->r0kh_list = NULL; + while (r0kh) { + r0kh_prev = r0kh; + r0kh = r0kh->next; + os_free(r0kh_prev); + } + + r1kh = conf->r1kh_list; + conf->r1kh_list = NULL; + while (r1kh) { + r1kh_prev = r1kh; + r1kh = r1kh->next; + os_free(r1kh_prev); + } + } +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_WPS + os_free(conf->wps_pin_requests); + os_free(conf->device_name); + os_free(conf->manufacturer); + os_free(conf->model_name); + os_free(conf->model_number); + os_free(conf->serial_number); + os_free(conf->device_type); + os_free(conf->config_methods); + os_free(conf->ap_pin); + os_free(conf->extra_cred); + os_free(conf->ap_settings); + os_free(conf->upnp_iface); + os_free(conf->friendly_name); + os_free(conf->manufacturer_url); + os_free(conf->model_description); + os_free(conf->model_url); + os_free(conf->upc); +#endif /* CONFIG_WPS */ +} + + +/** + * hostapd_config_free - Free hostapd configuration + * @conf: Configuration data from hostapd_config_read(). + */ +void hostapd_config_free(struct hostapd_config *conf) +{ + size_t i; + + if (conf == NULL) + return; + + for (i = 0; i < conf->num_bss; i++) + hostapd_config_free_bss(&conf->bss[i]); + os_free(conf->bss); + os_free(conf->supported_rates); + os_free(conf->basic_rates); + + os_free(conf); +} + + +/** + * hostapd_maclist_found - Find a MAC address from a list + * @list: MAC address list + * @num_entries: Number of addresses in the list + * @addr: Address to search for + * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed + * Returns: 1 if address is in the list or 0 if not. + * + * Perform a binary search for given MAC address from a pre-sorted list. + */ +int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, + const u8 *addr, int *vlan_id) +{ + int start, end, middle, res; + + start = 0; + end = num_entries - 1; + + while (start <= end) { + middle = (start + end) / 2; + res = os_memcmp(list[middle].addr, addr, ETH_ALEN); + if (res == 0) { + if (vlan_id) + *vlan_id = list[middle].vlan_id; + return 1; + } + if (res < 0) + start = middle + 1; + else + end = middle - 1; + } + + return 0; +} + + +int hostapd_rate_found(int *list, int rate) +{ + int i; + + if (list == NULL) + return 0; + + for (i = 0; list[i] >= 0; i++) + if (list[i] == rate) + return 1; + + return 0; +} + + +const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, int vlan_id) +{ + struct hostapd_vlan *v = vlan; + while (v) { + if (v->vlan_id == vlan_id || v->vlan_id == VLAN_ID_WILDCARD) + return v->ifname; + v = v->next; + } + return NULL; +} + + +const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, + const u8 *addr, const u8 *prev_psk) +{ + struct hostapd_wpa_psk *psk; + int next_ok = prev_psk == NULL; + + for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) { + if (next_ok && + (psk->group || os_memcmp(psk->addr, addr, ETH_ALEN) == 0)) + return psk->psk; + + if (psk->psk == prev_psk) + next_ok = 1; + } + + return NULL; +} + + +const struct hostapd_eap_user * +hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity, + size_t identity_len, int phase2) +{ + struct hostapd_eap_user *user = conf->eap_user; + +#ifdef CONFIG_WPS + if (conf->wps_state && identity_len == WSC_ID_ENROLLEE_LEN && + os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0) { + static struct hostapd_eap_user wsc_enrollee; + os_memset(&wsc_enrollee, 0, sizeof(wsc_enrollee)); + wsc_enrollee.methods[0].method = eap_server_get_type( + "WSC", &wsc_enrollee.methods[0].vendor); + return &wsc_enrollee; + } + + if (conf->wps_state && identity_len == WSC_ID_REGISTRAR_LEN && + os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0) { + static struct hostapd_eap_user wsc_registrar; + os_memset(&wsc_registrar, 0, sizeof(wsc_registrar)); + wsc_registrar.methods[0].method = eap_server_get_type( + "WSC", &wsc_registrar.methods[0].vendor); + wsc_registrar.password = (u8 *) conf->ap_pin; + wsc_registrar.password_len = conf->ap_pin ? + os_strlen(conf->ap_pin) : 0; + return &wsc_registrar; + } +#endif /* CONFIG_WPS */ + + while (user) { + if (!phase2 && user->identity == NULL) { + /* Wildcard match */ + break; + } + + if (user->phase2 == !!phase2 && user->wildcard_prefix && + identity_len >= user->identity_len && + os_memcmp(user->identity, identity, user->identity_len) == + 0) { + /* Wildcard prefix match */ + break; + } + + if (user->phase2 == !!phase2 && + user->identity_len == identity_len && + os_memcmp(user->identity, identity, identity_len) == 0) + break; + user = user->next; + } + + return user; +} diff --git a/contrib/wpa/hostapd/config.h b/contrib/wpa/src/ap/ap_config.h similarity index 90% rename from contrib/wpa/hostapd/config.h rename to contrib/wpa/src/ap/ap_config.h index ea530d45d169..f509b5bbb197 100644 --- a/contrib/wpa/hostapd/config.h +++ b/contrib/wpa/src/ap/ap_config.h @@ -1,7 +1,6 @@ /* - * hostapd / Configuration file - * Copyright (c) 2003-2007, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation + * hostapd / Configuration definitions and helpers functions + * Copyright (c) 2003-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,16 +12,15 @@ * See README and COPYING for more details. */ -#ifndef CONFIG_H -#define CONFIG_H +#ifndef HOSTAPD_CONFIG_H +#define HOSTAPD_CONFIG_H -#include "defs.h" +#include "common/defs.h" #include "ip_addr.h" -#include "wpa_common.h" +#include "common/wpa_common.h" -#ifndef IFNAMSIZ -#define IFNAMSIZ 16 -#endif +#define MAX_STA_COUNT 2007 +#define MAX_VLAN_ID 4094 typedef u8 macaddr[ETH_ALEN]; @@ -171,6 +169,7 @@ struct hostapd_bss_config { struct hostapd_ip_addr own_ip_addr; char *nas_identifier; struct hostapd_radius_servers *radius; + int acct_interim_interval; struct hostapd_ssid ssid; @@ -198,6 +197,7 @@ struct hostapd_bss_config { int num_accept_mac; struct mac_acl_entry *deny_mac; int num_deny_mac; + int wds_sta; int auth_algs; /* bitfield of allowed IEEE 802.11 authentication * algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */ @@ -205,11 +205,7 @@ struct hostapd_bss_config { int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */ int wpa_key_mgmt; #ifdef CONFIG_IEEE80211W - enum { - NO_IEEE80211W = 0, - IEEE80211W_OPTIONAL = 1, - IEEE80211W_REQUIRED = 2 - } ieee80211w; + enum mfp_options ieee80211w; /* dot11AssociationSAQueryMaximumTimeout (in TUs) */ unsigned int assoc_sa_query_max_timeout; /* dot11AssociationSAQueryRetryTimeout (in TUs) */ @@ -238,7 +234,9 @@ struct hostapd_bss_config { #endif /* CONFIG_IEEE80211R */ char *ctrl_interface; /* directory for UNIX domain sockets */ +#ifndef CONFIG_NATIVE_WINDOWS gid_t ctrl_interface_gid; +#endif /* CONFIG_NATIVE_WINDOWS */ int ctrl_interface_gid_set; char *ca_cert; @@ -272,6 +270,7 @@ struct hostapd_bss_config { int ignore_broadcast_ssid; int wmm_enabled; + int wmm_uapsd; struct hostapd_vlan *vlan, *vlan_tail; @@ -316,14 +315,6 @@ struct hostapd_bss_config { }; -typedef enum { - HOSTAPD_MODE_IEEE80211B, - HOSTAPD_MODE_IEEE80211G, - HOSTAPD_MODE_IEEE80211A, - NUM_HOSTAPD_MODES -} hostapd_hw_mode; - - /** * struct hostapd_config - Per-radio interface configuration */ @@ -336,7 +327,7 @@ struct hostapd_config { int fragm_threshold; u8 send_probe_response; u8 channel; - hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */ + enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */ enum { LONG_PREAMBLE = 0, SHORT_PREAMBLE = 1 @@ -353,9 +344,6 @@ struct hostapd_config { const struct wpa_driver_ops *driver; - int passive_scan_interval; /* seconds, 0 = disabled */ - int passive_scan_listen; /* usec */ - int passive_scan_mode; int ap_table_max_size; int ap_table_expiration_time; @@ -379,16 +367,8 @@ struct hostapd_config { */ struct hostapd_wmm_ac_params wmm_ac_params[4]; - enum { - INTERNAL_BRIDGE_DO_NOT_CONTROL = -1, - INTERNAL_BRIDGE_DISABLED = 0, - INTERNAL_BRIDGE_ENABLED = 1 - } bridge_packets; - -#ifdef CONFIG_IEEE80211N int ht_op_mode_fixed; u16 ht_capab; -#endif /* CONFIG_IEEE80211N */ int ieee80211n; int secondary_channel; }; @@ -396,7 +376,8 @@ struct hostapd_config { int hostapd_mac_comp(const void *a, const void *b); int hostapd_mac_comp_empty(const void *a); -struct hostapd_config * hostapd_config_read(const char *fname); +struct hostapd_config * hostapd_config_defaults(void); +void hostapd_config_defaults_bss(struct hostapd_bss_config *bss); void hostapd_config_free(struct hostapd_config *conf); int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, const u8 *addr, int *vlan_id); @@ -412,4 +393,4 @@ const struct hostapd_eap_user * hostapd_get_eap_user(const struct hostapd_bss_config *conf, const u8 *identity, size_t identity_len, int phase2); -#endif /* CONFIG_H */ +#endif /* HOSTAPD_CONFIG_H */ diff --git a/contrib/wpa/src/ap/ap_drv_ops.c b/contrib/wpa/src/ap/ap_drv_ops.c new file mode 100644 index 000000000000..f264a3e407ff --- /dev/null +++ b/contrib/wpa/src/ap/ap_drv_ops.c @@ -0,0 +1,621 @@ +/* + * hostapd - Driver operations + * Copyright (c) 2009-2010, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "drivers/driver.h" +#include "common/ieee802_11_defs.h" +#include "hostapd.h" +#include "ieee802_11.h" +#include "sta_info.h" +#include "ap_config.h" +#include "ap_drv_ops.h" + + +static int hostapd_sta_flags_to_drv(int flags) +{ + int res = 0; + if (flags & WLAN_STA_AUTHORIZED) + res |= WPA_STA_AUTHORIZED; + if (flags & WLAN_STA_WMM) + res |= WPA_STA_WMM; + if (flags & WLAN_STA_SHORT_PREAMBLE) + res |= WPA_STA_SHORT_PREAMBLE; + if (flags & WLAN_STA_MFP) + res |= WPA_STA_MFP; + return res; +} + + +static int hostapd_set_ap_wps_ie(struct hostapd_data *hapd) +{ + struct wpabuf *beacon, *proberesp; + int ret; + + if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) + return 0; + + beacon = hapd->wps_beacon_ie; + proberesp = hapd->wps_probe_resp_ie; + + ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp); + + return ret; +} + + +static int hostapd_send_mgmt_frame(struct hostapd_data *hapd, const void *msg, + size_t len) +{ + if (hapd->driver == NULL || hapd->driver->send_mlme == NULL) + return 0; + return hapd->driver->send_mlme(hapd->drv_priv, msg, len); +} + + +static int hostapd_send_eapol(struct hostapd_data *hapd, const u8 *addr, + const u8 *data, size_t data_len, int encrypt) +{ + if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL) + return 0; + return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data, + data_len, encrypt, + hapd->own_addr); +} + + +static int hostapd_set_authorized(struct hostapd_data *hapd, + struct sta_info *sta, int authorized) +{ + if (authorized) { + return hostapd_sta_set_flags(hapd, sta->addr, + hostapd_sta_flags_to_drv( + sta->flags), + WPA_STA_AUTHORIZED, ~0); + } + + return hostapd_sta_set_flags(hapd, sta->addr, + hostapd_sta_flags_to_drv(sta->flags), + 0, ~WPA_STA_AUTHORIZED); +} + + +static int hostapd_set_key(const char *ifname, struct hostapd_data *hapd, + enum wpa_alg alg, const u8 *addr, int key_idx, + int set_tx, const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len) +{ + if (hapd->driver == NULL || hapd->driver->set_key == NULL) + return 0; + return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr, + key_idx, set_tx, seq, seq_len, key, + key_len); +} + + +static int hostapd_read_sta_data(struct hostapd_data *hapd, + struct hostap_sta_driver_data *data, + const u8 *addr) +{ + if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL) + return -1; + return hapd->driver->read_sta_data(hapd->drv_priv, data, addr); +} + + +static int hostapd_sta_clear_stats(struct hostapd_data *hapd, const u8 *addr) +{ + if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL) + return 0; + return hapd->driver->sta_clear_stats(hapd->drv_priv, addr); +} + + +static int hostapd_set_sta_flags(struct hostapd_data *hapd, + struct sta_info *sta) +{ + int set_flags, total_flags, flags_and, flags_or; + total_flags = hostapd_sta_flags_to_drv(sta->flags); + set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP; + if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) || + sta->auth_alg == WLAN_AUTH_FT) && + sta->flags & WLAN_STA_AUTHORIZED) + set_flags |= WPA_STA_AUTHORIZED; + flags_or = total_flags & set_flags; + flags_and = total_flags | ~set_flags; + return hostapd_sta_set_flags(hapd, sta->addr, total_flags, + flags_or, flags_and); +} + + +static int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, + const char *ifname, int enabled) +{ + struct wpa_bss_params params; + os_memset(¶ms, 0, sizeof(params)); + params.ifname = ifname; + params.enabled = enabled; + if (enabled) { + params.wpa = hapd->conf->wpa; + params.ieee802_1x = hapd->conf->ieee802_1x; + params.wpa_group = hapd->conf->wpa_group; + params.wpa_pairwise = hapd->conf->wpa_pairwise; + params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt; + params.rsn_preauth = hapd->conf->rsn_preauth; + } + return hostapd_set_ieee8021x(hapd, ¶ms); +} + + +static int hostapd_set_radius_acl_auth(struct hostapd_data *hapd, + const u8 *mac, int accepted, + u32 session_timeout) +{ + if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL) + return 0; + return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted, + session_timeout); +} + + +static int hostapd_set_radius_acl_expire(struct hostapd_data *hapd, + const u8 *mac) +{ + if (hapd->driver == NULL || + hapd->driver->set_radius_acl_expire == NULL) + return 0; + return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac); +} + + +static int hostapd_set_bss_params(struct hostapd_data *hapd, + int use_protection) +{ + int ret = 0; + int preamble; +#ifdef CONFIG_IEEE80211N + u8 buf[60], *ht_capab, *ht_oper, *pos; + + pos = buf; + ht_capab = pos; + pos = hostapd_eid_ht_capabilities(hapd, pos); + ht_oper = pos; + pos = hostapd_eid_ht_operation(hapd, pos); + if (pos > ht_oper && ht_oper > ht_capab && + hostapd_set_ht_params(hapd, ht_capab + 2, ht_capab[1], + ht_oper + 2, ht_oper[1])) { + wpa_printf(MSG_ERROR, "Could not set HT capabilities " + "for kernel driver"); + ret = -1; + } + +#endif /* CONFIG_IEEE80211N */ + + if (hostapd_set_cts_protect(hapd, use_protection)) { + wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel " + "driver"); + ret = -1; + } + + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && + hostapd_set_short_slot_time(hapd, + hapd->iface->num_sta_no_short_slot_time + > 0 ? 0 : 1)) { + wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option " + "in kernel driver"); + ret = -1; + } + + if (hapd->iface->num_sta_no_short_preamble == 0 && + hapd->iconf->preamble == SHORT_PREAMBLE) + preamble = SHORT_PREAMBLE; + else + preamble = LONG_PREAMBLE; + if (hostapd_set_preamble(hapd, preamble)) { + wpa_printf(MSG_ERROR, "Could not set preamble for kernel " + "driver"); + ret = -1; + } + + return ret; +} + + +static int hostapd_set_beacon(struct hostapd_data *hapd, + const u8 *head, size_t head_len, + const u8 *tail, size_t tail_len, int dtim_period, + int beacon_int) +{ + if (hapd->driver == NULL || hapd->driver->set_beacon == NULL) + return 0; + return hapd->driver->set_beacon(hapd->drv_priv, + head, head_len, tail, tail_len, + dtim_period, beacon_int); +} + + +static int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname) +{ + char force_ifname[IFNAMSIZ]; + u8 if_addr[ETH_ALEN]; + return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL, NULL, + force_ifname, if_addr); +} + +static int hostapd_vlan_if_remove(struct hostapd_data *hapd, + const char *ifname) +{ + return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname); +} + + +static int hostapd_set_wds_sta(struct hostapd_data *hapd, const u8 *addr, + int aid, int val) +{ + if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL) + return 0; + return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val); +} + + +static int hostapd_set_sta_vlan(const char *ifname, struct hostapd_data *hapd, + const u8 *addr, int vlan_id) +{ + if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL) + return 0; + return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname, + vlan_id); +} + + +static int hostapd_get_inact_sec(struct hostapd_data *hapd, const u8 *addr) +{ + if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL) + return 0; + return hapd->driver->get_inact_sec(hapd->drv_priv, addr); +} + + +static int hostapd_sta_deauth(struct hostapd_data *hapd, const u8 *addr, + int reason) +{ + if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL) + return 0; + return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr, + reason); +} + + +static int hostapd_sta_disassoc(struct hostapd_data *hapd, const u8 *addr, + int reason) +{ + if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL) + return 0; + return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr, + reason); +} + + +static int hostapd_sta_add(struct hostapd_data *hapd, + const u8 *addr, u16 aid, u16 capability, + const u8 *supp_rates, size_t supp_rates_len, + u16 listen_interval, + const struct ieee80211_ht_capabilities *ht_capab) +{ + struct hostapd_sta_add_params params; + + if (hapd->driver == NULL) + return 0; + if (hapd->driver->sta_add == NULL) + return 0; + + os_memset(¶ms, 0, sizeof(params)); + params.addr = addr; + params.aid = aid; + params.capability = capability; + params.supp_rates = supp_rates; + params.supp_rates_len = supp_rates_len; + params.listen_interval = listen_interval; + params.ht_capabilities = ht_capab; + return hapd->driver->sta_add(hapd->drv_priv, ¶ms); +} + + +static int hostapd_sta_remove(struct hostapd_data *hapd, const u8 *addr) +{ + if (hapd->driver == NULL || hapd->driver->sta_remove == NULL) + return 0; + return hapd->driver->sta_remove(hapd->drv_priv, addr); +} + + +static int hostapd_set_countermeasures(struct hostapd_data *hapd, int enabled) +{ + if (hapd->driver == NULL || + hapd->driver->hapd_set_countermeasures == NULL) + return 0; + return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled); +} + + +void hostapd_set_driver_ops(struct hostapd_driver_ops *ops) +{ + ops->set_ap_wps_ie = hostapd_set_ap_wps_ie; + ops->send_mgmt_frame = hostapd_send_mgmt_frame; + ops->send_eapol = hostapd_send_eapol; + ops->set_authorized = hostapd_set_authorized; + ops->set_key = hostapd_set_key; + ops->read_sta_data = hostapd_read_sta_data; + ops->sta_clear_stats = hostapd_sta_clear_stats; + ops->set_sta_flags = hostapd_set_sta_flags; + ops->set_drv_ieee8021x = hostapd_set_drv_ieee8021x; + ops->set_radius_acl_auth = hostapd_set_radius_acl_auth; + ops->set_radius_acl_expire = hostapd_set_radius_acl_expire; + ops->set_bss_params = hostapd_set_bss_params; + ops->set_beacon = hostapd_set_beacon; + ops->vlan_if_add = hostapd_vlan_if_add; + ops->vlan_if_remove = hostapd_vlan_if_remove; + ops->set_wds_sta = hostapd_set_wds_sta; + ops->set_sta_vlan = hostapd_set_sta_vlan; + ops->get_inact_sec = hostapd_get_inact_sec; + ops->sta_deauth = hostapd_sta_deauth; + ops->sta_disassoc = hostapd_sta_disassoc; + ops->sta_add = hostapd_sta_add; + ops->sta_remove = hostapd_sta_remove; + ops->set_countermeasures = hostapd_set_countermeasures; +} + + +int hostapd_set_privacy(struct hostapd_data *hapd, int enabled) +{ + if (hapd->driver == NULL || hapd->driver->set_privacy == NULL) + return 0; + return hapd->driver->set_privacy(hapd->drv_priv, enabled); +} + + +int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, + size_t elem_len) +{ + if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL) + return 0; + return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len); +} + + +int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len) +{ + if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL) + return 0; + return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len); +} + + +int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len) +{ + if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL) + return 0; + return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len); +} + + +int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, + const char *ifname, const u8 *addr, void *bss_ctx, + void **drv_priv, char *force_ifname, u8 *if_addr) +{ + if (hapd->driver == NULL || hapd->driver->if_add == NULL) + return -1; + return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr, + bss_ctx, drv_priv, force_ifname, if_addr); +} + + +int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, + const char *ifname) +{ + if (hapd->driver == NULL || hapd->driver->if_remove == NULL) + return -1; + return hapd->driver->if_remove(hapd->drv_priv, type, ifname); +} + + +int hostapd_set_ieee8021x(struct hostapd_data *hapd, + struct wpa_bss_params *params) +{ + if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL) + return 0; + return hapd->driver->set_ieee8021x(hapd->drv_priv, params); +} + + +int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd, + const u8 *addr, int idx, u8 *seq) +{ + if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL) + return 0; + return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx, + seq); +} + + +int hostapd_flush(struct hostapd_data *hapd) +{ + if (hapd->driver == NULL || hapd->driver->flush == NULL) + return 0; + return hapd->driver->flush(hapd->drv_priv); +} + + +int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq, + int channel, int ht_enabled, int sec_channel_offset) +{ + struct hostapd_freq_params data; + if (hapd->driver == NULL) + return 0; + if (hapd->driver->set_freq == NULL) + return 0; + os_memset(&data, 0, sizeof(data)); + data.mode = mode; + data.freq = freq; + data.channel = channel; + data.ht_enabled = ht_enabled; + data.sec_channel_offset = sec_channel_offset; + return hapd->driver->set_freq(hapd->drv_priv, &data); +} + +int hostapd_set_rts(struct hostapd_data *hapd, int rts) +{ + if (hapd->driver == NULL || hapd->driver->set_rts == NULL) + return 0; + return hapd->driver->set_rts(hapd->drv_priv, rts); +} + + +int hostapd_set_frag(struct hostapd_data *hapd, int frag) +{ + if (hapd->driver == NULL || hapd->driver->set_frag == NULL) + return 0; + return hapd->driver->set_frag(hapd->drv_priv, frag); +} + + +int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, + int total_flags, int flags_or, int flags_and) +{ + if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL) + return 0; + return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags, + flags_or, flags_and); +} + + +int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates, + int *basic_rates, int mode) +{ + if (hapd->driver == NULL || hapd->driver->set_rate_sets == NULL) + return 0; + return hapd->driver->set_rate_sets(hapd->drv_priv, supp_rates, + basic_rates, mode); +} + + +int hostapd_set_country(struct hostapd_data *hapd, const char *country) +{ + if (hapd->driver == NULL || + hapd->driver->set_country == NULL) + return 0; + return hapd->driver->set_country(hapd->drv_priv, country); +} + + +int hostapd_set_cts_protect(struct hostapd_data *hapd, int value) +{ + if (hapd->driver == NULL || hapd->driver->set_cts_protect == NULL) + return 0; + return hapd->driver->set_cts_protect(hapd->drv_priv, value); +} + + +int hostapd_set_preamble(struct hostapd_data *hapd, int value) +{ + if (hapd->driver == NULL || hapd->driver->set_preamble == NULL) + return 0; + return hapd->driver->set_preamble(hapd->drv_priv, value); +} + + +int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value) +{ + if (hapd->driver == NULL || hapd->driver->set_short_slot_time == NULL) + return 0; + return hapd->driver->set_short_slot_time(hapd->drv_priv, value); +} + + +int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, + int cw_min, int cw_max, int burst_time) +{ + if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL) + return 0; + return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs, + cw_min, cw_max, burst_time); +} + + +int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr, + const u8 *mask) +{ + if (hapd->driver == NULL || hapd->driver->valid_bss_mask == NULL) + return 1; + return hapd->driver->valid_bss_mask(hapd->drv_priv, addr, mask); +} + + +struct hostapd_hw_modes * +hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, + u16 *flags) +{ + if (hapd->driver == NULL || + hapd->driver->get_hw_feature_data == NULL) + return NULL; + return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes, + flags); +} + + +int hostapd_driver_commit(struct hostapd_data *hapd) +{ + if (hapd->driver == NULL || hapd->driver->commit == NULL) + return 0; + return hapd->driver->commit(hapd->drv_priv); +} + + +int hostapd_set_ht_params(struct hostapd_data *hapd, + const u8 *ht_capab, size_t ht_capab_len, + const u8 *ht_oper, size_t ht_oper_len) +{ + if (hapd->driver == NULL || hapd->driver->set_ht_params == NULL || + ht_capab == NULL || ht_oper == NULL) + return 0; + return hapd->driver->set_ht_params(hapd->drv_priv, + ht_capab, ht_capab_len, + ht_oper, ht_oper_len); +} + + +int hostapd_drv_none(struct hostapd_data *hapd) +{ + return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0; +} + + +int hostapd_driver_scan(struct hostapd_data *hapd, + struct wpa_driver_scan_params *params) +{ + if (hapd->driver && hapd->driver->scan2) + return hapd->driver->scan2(hapd->drv_priv, params); + return -1; +} + + +struct wpa_scan_results * hostapd_driver_get_scan_results( + struct hostapd_data *hapd) +{ + if (hapd->driver && hapd->driver->get_scan_results2) + return hapd->driver->get_scan_results2(hapd->drv_priv); + return NULL; +} diff --git a/contrib/wpa/src/ap/ap_drv_ops.h b/contrib/wpa/src/ap/ap_drv_ops.h new file mode 100644 index 000000000000..9b75d096a009 --- /dev/null +++ b/contrib/wpa/src/ap/ap_drv_ops.h @@ -0,0 +1,67 @@ +/* + * hostapd - Driver operations + * Copyright (c) 2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef AP_DRV_OPS +#define AP_DRV_OPS + +enum wpa_driver_if_type; +struct wpa_bss_params; +struct wpa_driver_scan_params; + +void hostapd_set_driver_ops(struct hostapd_driver_ops *ops); +int hostapd_set_privacy(struct hostapd_data *hapd, int enabled); +int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, + size_t elem_len); +int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len); +int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len); +int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, + const char *ifname, const u8 *addr, void *bss_ctx, + void **drv_priv, char *force_ifname, u8 *if_addr); +int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, + const char *ifname); +int hostapd_set_ieee8021x(struct hostapd_data *hapd, + struct wpa_bss_params *params); +int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd, + const u8 *addr, int idx, u8 *seq); +int hostapd_flush(struct hostapd_data *hapd); +int hostapd_set_freq(struct hostapd_data *hapd, int mode, int freq, + int channel, int ht_enabled, int sec_channel_offset); +int hostapd_set_rts(struct hostapd_data *hapd, int rts); +int hostapd_set_frag(struct hostapd_data *hapd, int frag); +int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, + int total_flags, int flags_or, int flags_and); +int hostapd_set_rate_sets(struct hostapd_data *hapd, int *supp_rates, + int *basic_rates, int mode); +int hostapd_set_country(struct hostapd_data *hapd, const char *country); +int hostapd_set_cts_protect(struct hostapd_data *hapd, int value); +int hostapd_set_preamble(struct hostapd_data *hapd, int value); +int hostapd_set_short_slot_time(struct hostapd_data *hapd, int value); +int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, + int cw_min, int cw_max, int burst_time); +int hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr, + const u8 *mask); +struct hostapd_hw_modes * +hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, + u16 *flags); +int hostapd_driver_commit(struct hostapd_data *hapd); +int hostapd_set_ht_params(struct hostapd_data *hapd, + const u8 *ht_capab, size_t ht_capab_len, + const u8 *ht_oper, size_t ht_oper_len); +int hostapd_drv_none(struct hostapd_data *hapd); +int hostapd_driver_scan(struct hostapd_data *hapd, + struct wpa_driver_scan_params *params); +struct wpa_scan_results * hostapd_driver_get_scan_results( + struct hostapd_data *hapd); + +#endif /* AP_DRV_OPS */ diff --git a/contrib/wpa/hostapd/ap_list.c b/contrib/wpa/src/ap/ap_list.c similarity index 71% rename from contrib/wpa/hostapd/ap_list.c rename to contrib/wpa/src/ap/ap_list.c index 4f217dc54121..5297dbf3bf5f 100644 --- a/contrib/wpa/hostapd/ap_list.c +++ b/contrib/wpa/src/ap/ap_list.c @@ -1,9 +1,8 @@ /* * hostapd / AP table - * Copyright (c) 2002-2003, Jouni Malinen + * Copyright (c) 2002-2009, Jouni Malinen * Copyright (c) 2003-2004, Instant802 Networks, Inc. * Copyright (c) 2006, Devicescape Software, Inc. - * Copyright (c) 2007-2008, Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -15,52 +14,19 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "drivers/driver.h" #include "hostapd.h" +#include "ap_config.h" #include "ieee802_11.h" -#include "eloop.h" -#include "ap_list.h" -#include "hw_features.h" +#include "sta_info.h" #include "beacon.h" - - -struct ieee80211_frame_info { - u32 version; - u32 length; - u64 mactime; - u64 hosttime; - u32 phytype; - u32 channel; - u32 datarate; - u32 antenna; - u32 priority; - u32 ssi_type; - u32 ssi_signal; - u32 ssi_noise; - u32 preamble; - u32 encoding; - - /* Note: this structure is otherwise identical to capture format used - * in linux-wlan-ng, but this additional field is used to provide meta - * data about the frame to hostapd. This was the easiest method for - * providing this information, but this might change in the future. */ - u32 msg_type; -} __attribute__ ((packed)); - - -enum ieee80211_phytype { - ieee80211_phytype_fhss_dot11_97 = 1, - ieee80211_phytype_dsss_dot11_97 = 2, - ieee80211_phytype_irbaseband = 3, - ieee80211_phytype_dsss_dot11_b = 4, - ieee80211_phytype_pbcc_dot11_b = 5, - ieee80211_phytype_ofdm_dot11_g = 6, - ieee80211_phytype_pbcc_dot11_g = 7, - ieee80211_phytype_ofdm_dot11_a = 8, - ieee80211_phytype_dsss_dot11_turbog = 255, - ieee80211_phytype_dsss_dot11_turbo = 256, -}; +#include "ap_list.h" /* AP list is a double linked list with head->prev pointing to the end of the @@ -69,29 +35,11 @@ enum ieee80211_phytype { * in this link will thus be the least recently used entry. */ -static void ap_list_new_ap(struct hostapd_iface *iface, struct ap_info *ap) -{ - wpa_printf(MSG_DEBUG, "New AP detected: " MACSTR, MAC2STR(ap->addr)); - - /* TODO: could send a notification message to an external program that - * would then determine whether a rogue AP has been detected */ -} - - -static void ap_list_expired_ap(struct hostapd_iface *iface, struct ap_info *ap) -{ - wpa_printf(MSG_DEBUG, "AP info expired: " MACSTR, MAC2STR(ap->addr)); - - /* TODO: could send a notification message to an external program */ -} - - static int ap_list_beacon_olbc(struct hostapd_iface *iface, struct ap_info *ap) { int i; if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G || - ap->phytype != ieee80211_phytype_pbcc_dot11_g || iface->conf->channel != ap->channel) return 0; @@ -108,16 +56,7 @@ static int ap_list_beacon_olbc(struct hostapd_iface *iface, struct ap_info *ap) } -#ifdef CONFIG_IEEE80211N -static int ap_list_beacon_olbc_ht(struct hostapd_iface *iface, - struct ap_info *ap) -{ - return !ap->ht_support; -} -#endif /* CONFIG_IEEE80211N */ - - -struct ap_info * ap_get_ap(struct hostapd_iface *iface, u8 *ap) +struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *ap) { struct ap_info *s; @@ -257,7 +196,7 @@ int ap_ap_for_each(struct hostapd_iface *iface, } -static struct ap_info * ap_ap_add(struct hostapd_iface *iface, u8 *addr) +static struct ap_info * ap_ap_add(struct hostapd_iface *iface, const u8 *addr) { struct ap_info *ap; @@ -275,8 +214,6 @@ static struct ap_info * ap_ap_add(struct hostapd_iface *iface, u8 *addr) if (iface->num_ap > iface->conf->ap_table_max_size && ap != ap->prev) { wpa_printf(MSG_DEBUG, "Removing the least recently used AP " MACSTR " from AP table", MAC2STR(ap->prev->addr)); - if (iface->conf->passive_scan_interval > 0) - ap_list_expired_ap(iface, ap->prev); ap_free_ap(iface, ap->prev); } @@ -285,7 +222,7 @@ static struct ap_info * ap_ap_add(struct hostapd_iface *iface, u8 *addr) void ap_list_process_beacon(struct hostapd_iface *iface, - struct ieee80211_mgmt *mgmt, + const struct ieee80211_mgmt *mgmt, struct ieee802_11_elems *elems, struct hostapd_frame_info *fi) { @@ -357,15 +294,11 @@ void ap_list_process_beacon(struct hostapd_iface *iface, ap->num_beacons++; time(&ap->last_beacon); if (fi) { - ap->phytype = fi->phytype; ap->ssi_signal = fi->ssi_signal; ap->datarate = fi->datarate; } - if (new_ap) { - if (iface->conf->passive_scan_interval > 0) - ap_list_new_ap(iface, ap); - } else if (ap != iface->ap_list) { + if (!new_ap && ap != iface->ap_list) { /* move AP entry into the beginning of the list so that the * oldest entry is always in the end of the list */ ap_ap_list_del(iface, ap); @@ -381,7 +314,7 @@ void ap_list_process_beacon(struct hostapd_iface *iface, } #ifdef CONFIG_IEEE80211N - if (!iface->olbc_ht && ap_list_beacon_olbc_ht(iface, ap)) { + if (!iface->olbc_ht && !ap->ht_support) { iface->olbc_ht = 1; hostapd_ht_operation_update(iface); wpa_printf(MSG_DEBUG, "OLBC HT AP detected: " MACSTR @@ -409,18 +342,12 @@ static void ap_list_timer(void *eloop_ctx, void *timeout_ctx) time(&now); - /* FIX: it looks like jkm-Purina ended up in busy loop in this - * function. Apparently, something can still cause a loop in the AP - * list.. */ - while (iface->ap_list) { ap = iface->ap_list->prev; if (ap->last_beacon + iface->conf->ap_table_expiration_time >= now) break; - if (iface->conf->passive_scan_interval > 0) - ap_list_expired_ap(iface, ap); ap_free_ap(iface, ap); } @@ -432,10 +359,8 @@ static void ap_list_timer(void *eloop_ctx, void *timeout_ctx) while (ap && (olbc == 0 || olbc_ht == 0)) { if (ap_list_beacon_olbc(iface, ap)) olbc = 1; -#ifdef CONFIG_IEEE80211N - if (ap_list_beacon_olbc_ht(iface, ap)) + if (!ap->ht_support) olbc_ht = 1; -#endif /* CONFIG_IEEE80211N */ ap = ap->next; } if (!olbc && iface->olbc) { @@ -470,32 +395,3 @@ void ap_list_deinit(struct hostapd_iface *iface) eloop_cancel_timeout(ap_list_timer, iface, NULL); hostapd_free_aps(iface); } - - -int ap_list_reconfig(struct hostapd_iface *iface, - struct hostapd_config *oldconf) -{ - time_t now; - struct ap_info *ap; - - if (iface->conf->ap_table_max_size == oldconf->ap_table_max_size && - iface->conf->ap_table_expiration_time == - oldconf->ap_table_expiration_time) - return 0; - - time(&now); - - while (iface->ap_list) { - ap = iface->ap_list->prev; - if (iface->num_ap <= iface->conf->ap_table_max_size && - ap->last_beacon + iface->conf->ap_table_expiration_time >= - now) - break; - - if (iface->conf->passive_scan_interval > 0) - ap_list_expired_ap(iface, iface->ap_list->prev); - ap_free_ap(iface, iface->ap_list->prev); - } - - return 0; -} diff --git a/contrib/wpa/hostapd/ap_list.h b/contrib/wpa/src/ap/ap_list.h similarity index 86% rename from contrib/wpa/hostapd/ap_list.h rename to contrib/wpa/src/ap/ap_list.h index 93704f8bb612..f49f58b54e43 100644 --- a/contrib/wpa/hostapd/ap_list.h +++ b/contrib/wpa/src/ap/ap_list.h @@ -3,7 +3,6 @@ * Copyright (c) 2002-2003, Jouni Malinen * Copyright (c) 2003-2004, Instant802 Networks, Inc. * Copyright (c) 2006, Devicescape Software, Inc. - * Copyright (c) 2007-2008, Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -39,7 +38,6 @@ struct ap_info { int wpa; int erp; /* ERP Info or -1 if ERP info element not present */ - int phytype; /* .11a / .11b / .11g / Atheros Turbo */ int channel; int datarate; /* in 100 kbps */ int ssi_signal; @@ -56,16 +54,25 @@ struct ap_info { struct ieee802_11_elems; struct hostapd_frame_info; -struct ap_info * ap_get_ap(struct hostapd_iface *iface, u8 *sta); +struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *sta); int ap_ap_for_each(struct hostapd_iface *iface, int (*func)(struct ap_info *s, void *data), void *data); void ap_list_process_beacon(struct hostapd_iface *iface, - struct ieee80211_mgmt *mgmt, + const struct ieee80211_mgmt *mgmt, struct ieee802_11_elems *elems, struct hostapd_frame_info *fi); +#ifdef NEED_AP_MLME int ap_list_init(struct hostapd_iface *iface); void ap_list_deinit(struct hostapd_iface *iface); -int ap_list_reconfig(struct hostapd_iface *iface, - struct hostapd_config *oldconf); +#else /* NEED_AP_MLME */ +static inline int ap_list_init(struct hostapd_iface *iface) +{ + return 0; +} + +static inline void ap_list_deinit(struct hostapd_iface *iface) +{ +} +#endif /* NEED_AP_MLME */ #endif /* AP_LIST_H */ diff --git a/contrib/wpa/hostapd/mlme.c b/contrib/wpa/src/ap/ap_mlme.c similarity index 95% rename from contrib/wpa/hostapd/mlme.c rename to contrib/wpa/src/ap/ap_mlme.c index d883931cf414..2b09b11e79c1 100644 --- a/contrib/wpa/hostapd/mlme.c +++ b/contrib/wpa/src/ap/ap_mlme.c @@ -14,14 +14,17 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" -#include "hostapd.h" +#include "utils/common.h" +#include "common/ieee802_11_defs.h" #include "ieee802_11.h" -#include "wpa.h" -#include "mlme.h" +#include "wpa_auth.h" +#include "sta_info.h" +#include "ap_mlme.h" +#ifndef CONFIG_NO_HOSTAPD_LOGGER static const char * mlme_auth_alg_str(int alg) { switch (alg) { @@ -35,6 +38,7 @@ static const char * mlme_auth_alg_str(int alg) return "unknown"; } +#endif /* CONFIG_NO_HOSTAPD_LOGGER */ /** diff --git a/contrib/wpa/hostapd/mlme.h b/contrib/wpa/src/ap/ap_mlme.h similarity index 100% rename from contrib/wpa/hostapd/mlme.h rename to contrib/wpa/src/ap/ap_mlme.h diff --git a/contrib/wpa/src/ap/authsrv.c b/contrib/wpa/src/ap/authsrv.c new file mode 100644 index 000000000000..0ab0668acc56 --- /dev/null +++ b/contrib/wpa/src/ap/authsrv.c @@ -0,0 +1,216 @@ +/* + * Authentication server setup + * Copyright (c) 2002-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "crypto/tls.h" +#include "eap_server/eap.h" +#include "eap_server/eap_sim_db.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "radius/radius_server.h" +#include "hostapd.h" +#include "ap_config.h" +#include "sta_info.h" +#include "authsrv.h" + + +#if defined(EAP_SERVER_SIM) || defined(EAP_SERVER_AKA) +#define EAP_SIM_DB +#endif /* EAP_SERVER_SIM || EAP_SERVER_AKA */ + + +#ifdef EAP_SIM_DB +static int hostapd_sim_db_cb_sta(struct hostapd_data *hapd, + struct sta_info *sta, void *ctx) +{ + if (eapol_auth_eap_pending_cb(sta->eapol_sm, ctx) == 0) + return 1; + return 0; +} + + +static void hostapd_sim_db_cb(void *ctx, void *session_ctx) +{ + struct hostapd_data *hapd = ctx; + if (ap_for_each_sta(hapd, hostapd_sim_db_cb_sta, session_ctx) == 0) { +#ifdef RADIUS_SERVER + radius_server_eap_pending_cb(hapd->radius_srv, session_ctx); +#endif /* RADIUS_SERVER */ + } +} +#endif /* EAP_SIM_DB */ + + +#ifdef RADIUS_SERVER + +static int hostapd_radius_get_eap_user(void *ctx, const u8 *identity, + size_t identity_len, int phase2, + struct eap_user *user) +{ + const struct hostapd_eap_user *eap_user; + int i, count; + + eap_user = hostapd_get_eap_user(ctx, identity, identity_len, phase2); + if (eap_user == NULL) + return -1; + + if (user == NULL) + return 0; + + os_memset(user, 0, sizeof(*user)); + count = EAP_USER_MAX_METHODS; + if (count > EAP_MAX_METHODS) + count = EAP_MAX_METHODS; + for (i = 0; i < count; i++) { + user->methods[i].vendor = eap_user->methods[i].vendor; + user->methods[i].method = eap_user->methods[i].method; + } + + if (eap_user->password) { + user->password = os_malloc(eap_user->password_len); + if (user->password == NULL) + return -1; + os_memcpy(user->password, eap_user->password, + eap_user->password_len); + user->password_len = eap_user->password_len; + user->password_hash = eap_user->password_hash; + } + user->force_version = eap_user->force_version; + user->ttls_auth = eap_user->ttls_auth; + + return 0; +} + + +static int hostapd_setup_radius_srv(struct hostapd_data *hapd) +{ + struct radius_server_conf srv; + struct hostapd_bss_config *conf = hapd->conf; + os_memset(&srv, 0, sizeof(srv)); + srv.client_file = conf->radius_server_clients; + srv.auth_port = conf->radius_server_auth_port; + srv.conf_ctx = conf; + srv.eap_sim_db_priv = hapd->eap_sim_db_priv; + srv.ssl_ctx = hapd->ssl_ctx; + srv.msg_ctx = hapd->msg_ctx; + srv.pac_opaque_encr_key = conf->pac_opaque_encr_key; + srv.eap_fast_a_id = conf->eap_fast_a_id; + srv.eap_fast_a_id_len = conf->eap_fast_a_id_len; + srv.eap_fast_a_id_info = conf->eap_fast_a_id_info; + srv.eap_fast_prov = conf->eap_fast_prov; + srv.pac_key_lifetime = conf->pac_key_lifetime; + srv.pac_key_refresh_time = conf->pac_key_refresh_time; + srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; + srv.tnc = conf->tnc; + srv.wps = hapd->wps; + srv.ipv6 = conf->radius_server_ipv6; + srv.get_eap_user = hostapd_radius_get_eap_user; + srv.eap_req_id_text = conf->eap_req_id_text; + srv.eap_req_id_text_len = conf->eap_req_id_text_len; + + hapd->radius_srv = radius_server_init(&srv); + if (hapd->radius_srv == NULL) { + wpa_printf(MSG_ERROR, "RADIUS server initialization failed."); + return -1; + } + + return 0; +} + +#endif /* RADIUS_SERVER */ + + +int authsrv_init(struct hostapd_data *hapd) +{ +#ifdef EAP_TLS_FUNCS + if (hapd->conf->eap_server && + (hapd->conf->ca_cert || hapd->conf->server_cert || + hapd->conf->dh_file)) { + struct tls_connection_params params; + + hapd->ssl_ctx = tls_init(NULL); + if (hapd->ssl_ctx == NULL) { + wpa_printf(MSG_ERROR, "Failed to initialize TLS"); + authsrv_deinit(hapd); + return -1; + } + + os_memset(¶ms, 0, sizeof(params)); + params.ca_cert = hapd->conf->ca_cert; + params.client_cert = hapd->conf->server_cert; + params.private_key = hapd->conf->private_key; + params.private_key_passwd = hapd->conf->private_key_passwd; + params.dh_file = hapd->conf->dh_file; + + if (tls_global_set_params(hapd->ssl_ctx, ¶ms)) { + wpa_printf(MSG_ERROR, "Failed to set TLS parameters"); + authsrv_deinit(hapd); + return -1; + } + + if (tls_global_set_verify(hapd->ssl_ctx, + hapd->conf->check_crl)) { + wpa_printf(MSG_ERROR, "Failed to enable check_crl"); + authsrv_deinit(hapd); + return -1; + } + } +#endif /* EAP_TLS_FUNCS */ + +#ifdef EAP_SIM_DB + if (hapd->conf->eap_sim_db) { + hapd->eap_sim_db_priv = + eap_sim_db_init(hapd->conf->eap_sim_db, + hostapd_sim_db_cb, hapd); + if (hapd->eap_sim_db_priv == NULL) { + wpa_printf(MSG_ERROR, "Failed to initialize EAP-SIM " + "database interface"); + authsrv_deinit(hapd); + return -1; + } + } +#endif /* EAP_SIM_DB */ + +#ifdef RADIUS_SERVER + if (hapd->conf->radius_server_clients && + hostapd_setup_radius_srv(hapd)) + return -1; +#endif /* RADIUS_SERVER */ + + return 0; +} + + +void authsrv_deinit(struct hostapd_data *hapd) +{ +#ifdef RADIUS_SERVER + radius_server_deinit(hapd->radius_srv); + hapd->radius_srv = NULL; +#endif /* RADIUS_SERVER */ + +#ifdef EAP_TLS_FUNCS + if (hapd->ssl_ctx) { + tls_deinit(hapd->ssl_ctx); + hapd->ssl_ctx = NULL; + } +#endif /* EAP_TLS_FUNCS */ + +#ifdef EAP_SIM_DB + if (hapd->eap_sim_db_priv) { + eap_sim_db_deinit(hapd->eap_sim_db_priv); + hapd->eap_sim_db_priv = NULL; + } +#endif /* EAP_SIM_DB */ +} diff --git a/contrib/wpa/src/ap/authsrv.h b/contrib/wpa/src/ap/authsrv.h new file mode 100644 index 000000000000..be3051ebfa2e --- /dev/null +++ b/contrib/wpa/src/ap/authsrv.h @@ -0,0 +1,21 @@ +/* + * Authentication server setup + * Copyright (c) 2002-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef AUTHSRV_H +#define AUTHSRV_H + +int authsrv_init(struct hostapd_data *hapd); +void authsrv_deinit(struct hostapd_data *hapd); + +#endif /* AUTHSRV_H */ diff --git a/contrib/wpa/hostapd/beacon.c b/contrib/wpa/src/ap/beacon.c similarity index 80% rename from contrib/wpa/hostapd/beacon.c rename to contrib/wpa/src/ap/beacon.c index 1f82d9cb7238..004cc8a5f336 100644 --- a/contrib/wpa/hostapd/beacon.c +++ b/contrib/wpa/src/ap/beacon.c @@ -2,8 +2,7 @@ * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response * Copyright (c) 2002-2004, Instant802 Networks, Inc. * Copyright (c) 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2008, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation + * Copyright (c) 2008-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -15,19 +14,21 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" #ifndef CONFIG_NATIVE_WINDOWS +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "drivers/driver.h" #include "hostapd.h" #include "ieee802_11.h" -#include "wpa.h" -#include "wme.h" -#include "beacon.h" -#include "hw_features.h" -#include "driver.h" +#include "wpa_auth.h" +#include "wmm.h" +#include "ap_config.h" #include "sta_info.h" -#include "wps_hostapd.h" +#include "beacon.h" static u8 ieee802_11_erp_info(struct hostapd_data *hapd) @@ -56,7 +57,8 @@ static u8 ieee802_11_erp_info(struct hostapd_data *hapd) } break; } - if (hapd->iface->num_sta_no_short_preamble > 0) + if (hapd->iface->num_sta_no_short_preamble > 0 || + hapd->iconf->preamble == LONG_PREAMBLE) erp |= ERP_INFO_BARKER_PREAMBLE_MODE; return erp; @@ -191,20 +193,26 @@ static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len, } -void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len) +void handle_probe_req(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len) { struct ieee80211_mgmt *resp; struct ieee802_11_elems elems; char *ssid; - u8 *pos, *epos, *ie; + u8 *pos, *epos; + const u8 *ie; size_t ssid_len, ie_len; struct sta_info *sta = NULL; + size_t buflen; + size_t i; ie = mgmt->u.probe_req.variable; ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req)); - hostapd_wps_probe_req_rx(hapd, mgmt->sa, ie, ie_len); + for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) + if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, + mgmt->sa, ie, ie_len) > 0) + return; if (!hapd->iconf->send_probe_response) return; @@ -258,7 +266,12 @@ void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, /* TODO: verify that supp_rates contains at least one matching rate * with AP configuration */ #define MAX_PROBERESP_LEN 768 - resp = os_zalloc(MAX_PROBERESP_LEN); + buflen = MAX_PROBERESP_LEN; +#ifdef CONFIG_WPS + if (hapd->wps_probe_resp_ie) + buflen += wpabuf_len(hapd->wps_probe_resp_ie); +#endif /* CONFIG_WPS */ + resp = os_zalloc(buflen); if (resp == NULL) return; epos = ((u8 *) resp) + MAX_PROBERESP_LEN; @@ -296,23 +309,26 @@ void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, /* Extended supported rates */ pos = hostapd_eid_ext_supp_rates(hapd, pos); + /* RSN, MDIE, WPA */ pos = hostapd_eid_wpa(hapd, pos, epos - pos, sta); +#ifdef CONFIG_IEEE80211N + pos = hostapd_eid_ht_capabilities(hapd, pos); + pos = hostapd_eid_ht_operation(hapd, pos); +#endif /* CONFIG_IEEE80211N */ + /* Wi-Fi Alliance WMM */ pos = hostapd_eid_wmm(hapd, pos); - pos = hostapd_eid_ht_capabilities_info(hapd, pos); - pos = hostapd_eid_ht_operation(hapd, pos); - #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) { - os_memcpy(pos, hapd->wps_probe_resp_ie, - hapd->wps_probe_resp_ie_len); - pos += hapd->wps_probe_resp_ie_len; + os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie), + wpabuf_len(hapd->wps_probe_resp_ie)); + pos += wpabuf_len(hapd->wps_probe_resp_ie); } #endif /* CONFIG_WPS */ - if (hostapd_send_mgmt_frame(hapd, resp, pos - (u8 *) resp, 0) < 0) + if (hapd->drv.send_mgmt_frame(hapd, resp, pos - (u8 *) resp) < 0) perror("handle_probe_req: send"); os_free(resp); @@ -327,16 +343,18 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd) { struct ieee80211_mgmt *head; u8 *pos, *tail, *tailpos; - int preamble; u16 capab_info; size_t head_len, tail_len; - int cts_protection = ((ieee802_11_erp_info(hapd) & - ERP_INFO_USE_PROTECTION) ? 1 : 0); #define BEACON_HEAD_BUF_SIZE 256 #define BEACON_TAIL_BUF_SIZE 512 head = os_zalloc(BEACON_HEAD_BUF_SIZE); - tailpos = tail = os_malloc(BEACON_TAIL_BUF_SIZE); + tail_len = BEACON_TAIL_BUF_SIZE; +#ifdef CONFIG_WPS + if (hapd->conf->wps_state && hapd->wps_beacon_ie) + tail_len += wpabuf_len(hapd->wps_beacon_ie); +#endif /* CONFIG_WPS */ + tailpos = tail = os_malloc(tail_len); if (head == NULL || tail == NULL) { wpa_printf(MSG_ERROR, "Failed to set beacon data"); os_free(head); @@ -392,68 +410,39 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd) /* Extended supported rates */ tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); + /* RSN, MDIE, WPA */ tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos, NULL); +#ifdef CONFIG_IEEE80211N + tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); + tailpos = hostapd_eid_ht_operation(hapd, tailpos); +#endif /* CONFIG_IEEE80211N */ + /* Wi-Fi Alliance WMM */ tailpos = hostapd_eid_wmm(hapd, tailpos); -#ifdef CONFIG_IEEE80211N - if (hapd->iconf->ieee80211n) { - u8 *ht_capab, *ht_oper; - ht_capab = tailpos; - tailpos = hostapd_eid_ht_capabilities_info(hapd, tailpos); - - ht_oper = tailpos; - tailpos = hostapd_eid_ht_operation(hapd, tailpos); - - if (tailpos > ht_oper && ht_oper > ht_capab && - hostapd_set_ht_params(hapd->conf->iface, hapd, - ht_capab + 2, ht_capab[1], - ht_oper + 2, ht_oper[1])) { - wpa_printf(MSG_ERROR, "Could not set HT capabilities " - "for kernel driver"); - } - } -#endif /* CONFIG_IEEE80211N */ - #ifdef CONFIG_WPS if (hapd->conf->wps_state && hapd->wps_beacon_ie) { - os_memcpy(tailpos, hapd->wps_beacon_ie, - hapd->wps_beacon_ie_len); - tailpos += hapd->wps_beacon_ie_len; + os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie), + wpabuf_len(hapd->wps_beacon_ie)); + tailpos += wpabuf_len(hapd->wps_beacon_ie); } #endif /* CONFIG_WPS */ tail_len = tailpos > tail ? tailpos - tail : 0; - if (hostapd_set_beacon(hapd->conf->iface, hapd, (u8 *) head, head_len, - tail, tail_len)) - wpa_printf(MSG_ERROR, "Failed to set beacon head/tail"); + if (hapd->drv.set_beacon(hapd, (u8 *) head, head_len, + tail, tail_len, hapd->conf->dtim_period, + hapd->iconf->beacon_int)) + wpa_printf(MSG_ERROR, "Failed to set beacon head/tail or DTIM " + "period"); os_free(tail); os_free(head); - if (hostapd_set_cts_protect(hapd, cts_protection)) - wpa_printf(MSG_ERROR, "Failed to set CTS protect in kernel " - "driver"); - - if (hapd->iface->current_mode && - hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && - hostapd_set_short_slot_time(hapd, - hapd->iface->num_sta_no_short_slot_time - > 0 ? 0 : 1)) - wpa_printf(MSG_ERROR, "Failed to set Short Slot Time option " - "in kernel driver"); - - if (hapd->iface->num_sta_no_short_preamble == 0 && - hapd->iconf->preamble == SHORT_PREAMBLE) - preamble = SHORT_PREAMBLE; - else - preamble = LONG_PREAMBLE; - if (hostapd_set_preamble(hapd, preamble)) - wpa_printf(MSG_ERROR, "Could not set preamble for kernel " - "driver"); + hapd->drv.set_bss_params(hapd, !!(ieee802_11_erp_info(hapd) & + ERP_INFO_USE_PROTECTION)); } diff --git a/contrib/wpa/hostapd/beacon.h b/contrib/wpa/src/ap/beacon.h similarity index 66% rename from contrib/wpa/hostapd/beacon.h rename to contrib/wpa/src/ap/beacon.h index 18e0da2e89f6..c1510e194254 100644 --- a/contrib/wpa/hostapd/beacon.h +++ b/contrib/wpa/src/ap/beacon.h @@ -16,9 +16,21 @@ #ifndef BEACON_H #define BEACON_H -void handle_probe_req(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len); +struct ieee80211_mgmt; + +void handle_probe_req(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len); +#ifdef NEED_AP_MLME void ieee802_11_set_beacon(struct hostapd_data *hapd); void ieee802_11_set_beacons(struct hostapd_iface *iface); +#else /* NEED_AP_MLME */ +static inline void ieee802_11_set_beacon(struct hostapd_data *hapd) +{ +} + +static inline void ieee802_11_set_beacons(struct hostapd_iface *iface) +{ +} +#endif /* NEED_AP_MLME */ #endif /* BEACON_H */ diff --git a/contrib/wpa/src/ap/ctrl_iface_ap.c b/contrib/wpa/src/ap/ctrl_iface_ap.c new file mode 100644 index 000000000000..e50b0a70ca95 --- /dev/null +++ b/contrib/wpa/src/ap/ctrl_iface_ap.c @@ -0,0 +1,104 @@ +/* + * Control interface for shared AP commands + * Copyright (c) 2004-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "hostapd.h" +#include "ieee802_1x.h" +#include "wpa_auth.h" +#include "ieee802_11.h" +#include "sta_info.h" +#include "wps_hostapd.h" +#include "ctrl_iface_ap.h" + + +static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, + struct sta_info *sta, + char *buf, size_t buflen) +{ + int len, res, ret; + + if (sta == NULL) { + ret = os_snprintf(buf, buflen, "FAIL\n"); + if (ret < 0 || (size_t) ret >= buflen) + return 0; + return ret; + } + + len = 0; + ret = os_snprintf(buf + len, buflen - len, MACSTR "\n", + MAC2STR(sta->addr)); + if (ret < 0 || (size_t) ret >= buflen - len) + return len; + len += ret; + + res = ieee802_11_get_mib_sta(hapd, sta, buf + len, buflen - len); + if (res >= 0) + len += res; + res = wpa_get_mib_sta(sta->wpa_sm, buf + len, buflen - len); + if (res >= 0) + len += res; + res = ieee802_1x_get_mib_sta(hapd, sta, buf + len, buflen - len); + if (res >= 0) + len += res; + res = hostapd_wps_get_mib_sta(hapd, sta->addr, buf + len, + buflen - len); + if (res >= 0) + len += res; + + return len; +} + + +int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd, + char *buf, size_t buflen) +{ + return hostapd_ctrl_iface_sta_mib(hapd, hapd->sta_list, buf, buflen); +} + + +int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr, + char *buf, size_t buflen) +{ + u8 addr[ETH_ALEN]; + int ret; + + if (hwaddr_aton(txtaddr, addr)) { + ret = os_snprintf(buf, buflen, "FAIL\n"); + if (ret < 0 || (size_t) ret >= buflen) + return 0; + return ret; + } + return hostapd_ctrl_iface_sta_mib(hapd, ap_get_sta(hapd, addr), + buf, buflen); +} + + +int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr, + char *buf, size_t buflen) +{ + u8 addr[ETH_ALEN]; + struct sta_info *sta; + int ret; + + if (hwaddr_aton(txtaddr, addr) || + (sta = ap_get_sta(hapd, addr)) == NULL) { + ret = os_snprintf(buf, buflen, "FAIL\n"); + if (ret < 0 || (size_t) ret >= buflen) + return 0; + return ret; + } + return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen); +} diff --git a/contrib/wpa/src/ap/ctrl_iface_ap.h b/contrib/wpa/src/ap/ctrl_iface_ap.h new file mode 100644 index 000000000000..8690beaad455 --- /dev/null +++ b/contrib/wpa/src/ap/ctrl_iface_ap.h @@ -0,0 +1,25 @@ +/* + * Control interface for shared AP commands + * Copyright (c) 2004-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef CTRL_IFACE_AP_H +#define CTRL_IFACE_AP_H + +int hostapd_ctrl_iface_sta_first(struct hostapd_data *hapd, + char *buf, size_t buflen); +int hostapd_ctrl_iface_sta(struct hostapd_data *hapd, const char *txtaddr, + char *buf, size_t buflen); +int hostapd_ctrl_iface_sta_next(struct hostapd_data *hapd, const char *txtaddr, + char *buf, size_t buflen); + +#endif /* CTRL_IFACE_AP_H */ diff --git a/contrib/wpa/src/ap/drv_callbacks.c b/contrib/wpa/src/ap/drv_callbacks.c new file mode 100644 index 000000000000..26ef5845abfd --- /dev/null +++ b/contrib/wpa/src/ap/drv_callbacks.c @@ -0,0 +1,457 @@ +/* + * hostapd / Callback functions for driver wrappers + * Copyright (c) 2002-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "radius/radius.h" +#include "drivers/driver.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" +#include "hostapd.h" +#include "ieee802_11.h" +#include "sta_info.h" +#include "accounting.h" +#include "tkip_countermeasures.h" +#include "iapp.h" +#include "ieee802_1x.h" +#include "wpa_auth.h" +#include "wmm.h" +#include "wps_hostapd.h" +#include "ap_config.h" + + +int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, + const u8 *ie, size_t ielen) +{ + struct sta_info *sta; + int new_assoc, res; + struct ieee802_11_elems elems; + + if (addr == NULL) { + /* + * This could potentially happen with unexpected event from the + * driver wrapper. This was seen at least in one case where the + * driver ended up being set to station mode while hostapd was + * running, so better make sure we stop processing such an + * event here. + */ + wpa_printf(MSG_DEBUG, "hostapd_notif_assoc: Skip event with " + "no address"); + return -1; + } + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "associated"); + + ieee802_11_parse_elems(ie, ielen, &elems, 0); + if (elems.wps_ie) { + ie = elems.wps_ie - 2; + ielen = elems.wps_ie_len + 2; + wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq"); + } else if (elems.rsn_ie) { + ie = elems.rsn_ie - 2; + ielen = elems.rsn_ie_len + 2; + wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq"); + } else if (elems.wpa_ie) { + ie = elems.wpa_ie - 2; + ielen = elems.wpa_ie_len + 2; + wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq"); + } else { + ie = NULL; + ielen = 0; + wpa_printf(MSG_DEBUG, "STA did not include WPS/RSN/WPA IE in " + "(Re)AssocReq"); + } + + sta = ap_get_sta(hapd, addr); + if (sta) { + accounting_sta_stop(hapd, sta); + } else { + sta = ap_sta_add(hapd, addr); + if (sta == NULL) + return -1; + } + sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); + + if (hapd->conf->wpa) { + if (ie == NULL || ielen == 0) { + if (hapd->conf->wps_state) { + wpa_printf(MSG_DEBUG, "STA did not include " + "WPA/RSN IE in (Re)Association " + "Request - possible WPS use"); + sta->flags |= WLAN_STA_MAYBE_WPS; + goto skip_wpa_check; + } + + wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA"); + return -1; + } + if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 && + os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { + sta->flags |= WLAN_STA_WPS; + goto skip_wpa_check; + } + + if (sta->wpa_sm == NULL) + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, + sta->addr); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_ERROR, "Failed to initialize WPA state " + "machine"); + return -1; + } + res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, + ie, ielen, NULL, 0); + if (res != WPA_IE_OK) { + int resp; + wpa_printf(MSG_DEBUG, "WPA/RSN information element " + "rejected? (res %u)", res); + wpa_hexdump(MSG_DEBUG, "IE", ie, ielen); + if (res == WPA_INVALID_GROUP) + resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID; + else if (res == WPA_INVALID_PAIRWISE) + resp = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID; + else if (res == WPA_INVALID_AKMP) + resp = WLAN_REASON_AKMP_NOT_VALID; +#ifdef CONFIG_IEEE80211W + else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) + resp = WLAN_REASON_INVALID_IE; + else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) + resp = WLAN_REASON_GROUP_CIPHER_NOT_VALID; +#endif /* CONFIG_IEEE80211W */ + else + resp = WLAN_REASON_INVALID_IE; + hapd->drv.sta_disassoc(hapd, sta->addr, resp); + ap_free_sta(hapd, sta); + return -1; + } + } else if (hapd->conf->wps_state) { + if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 && + os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { + sta->flags |= WLAN_STA_WPS; + } else + sta->flags |= WLAN_STA_MAYBE_WPS; + } +skip_wpa_check: + + new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; + sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; + wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); + + hostapd_new_assoc_sta(hapd, sta, !new_assoc); + + ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); + + return 0; +} + + +void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta; + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "disassociated"); + + sta = ap_get_sta(hapd, addr); + if (sta == NULL) { + wpa_printf(MSG_DEBUG, "Disassociation notification for " + "unknown STA " MACSTR, MAC2STR(addr)); + return; + } + + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR, + MAC2STR(sta->addr)); + wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); + sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); + ap_free_sta(hapd, sta); +} + + +#ifdef HOSTAPD + +#ifdef NEED_AP_MLME + +static const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len) +{ + u16 fc, type, stype; + + /* + * PS-Poll frames are 16 bytes. All other frames are + * 24 bytes or longer. + */ + if (len < 16) + return NULL; + + fc = le_to_host16(hdr->frame_control); + type = WLAN_FC_GET_TYPE(fc); + stype = WLAN_FC_GET_STYPE(fc); + + switch (type) { + case WLAN_FC_TYPE_DATA: + if (len < 24) + return NULL; + switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) { + case WLAN_FC_FROMDS | WLAN_FC_TODS: + case WLAN_FC_TODS: + return hdr->addr1; + case WLAN_FC_FROMDS: + return hdr->addr2; + default: + return NULL; + } + case WLAN_FC_TYPE_CTRL: + if (stype != WLAN_FC_STYPE_PSPOLL) + return NULL; + return hdr->addr1; + case WLAN_FC_TYPE_MGMT: + return hdr->addr3; + default: + return NULL; + } +} + + +#define HAPD_BROADCAST ((struct hostapd_data *) -1) + +static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface, + const u8 *bssid) +{ + size_t i; + + if (bssid == NULL) + return NULL; + if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff && + bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff) + return HAPD_BROADCAST; + + for (i = 0; i < iface->num_bss; i++) { + if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0) + return iface->bss[i]; + } + + return NULL; +} + + +static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd, + const u8 *frame, size_t len) +{ + const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame; + u16 fc = le_to_host16(hdr->frame_control); + hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len)); + if (hapd == NULL || hapd == HAPD_BROADCAST) + return; + + ieee802_11_rx_from_unknown(hapd, hdr->addr2, + (fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) == + (WLAN_FC_TODS | WLAN_FC_FROMDS)); +} + + +static void hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt) +{ + struct hostapd_iface *iface = hapd->iface; + const struct ieee80211_hdr *hdr; + const u8 *bssid; + struct hostapd_frame_info fi; + + hdr = (const struct ieee80211_hdr *) rx_mgmt->frame; + bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len); + if (bssid == NULL) + return; + + hapd = get_hapd_bssid(iface, bssid); + if (hapd == NULL) { + u16 fc; + fc = le_to_host16(hdr->frame_control); + + /* + * Drop frames to unknown BSSIDs except for Beacon frames which + * could be used to update neighbor information. + */ + if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) + hapd = iface->bss[0]; + else + return; + } + + os_memset(&fi, 0, sizeof(fi)); + fi.datarate = rx_mgmt->datarate; + fi.ssi_signal = rx_mgmt->ssi_signal; + + if (hapd == HAPD_BROADCAST) { + size_t i; + for (i = 0; i < iface->num_bss; i++) + ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame, + rx_mgmt->frame_len, &fi); + } else + ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, &fi); +} + + +static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf, + size_t len, u16 stype, int ok) +{ + struct ieee80211_hdr *hdr; + hdr = (struct ieee80211_hdr *) buf; + hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len)); + if (hapd == NULL || hapd == HAPD_BROADCAST) + return; + ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); +} + +#endif /* NEED_AP_MLME */ + + +static int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, + const u8 *ie, size_t ie_len) +{ + size_t i; + int ret = 0; + + for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) { + if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, + sa, ie, ie_len) > 0) { + ret = 1; + break; + } + } + return ret; +} + + +static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta = ap_get_sta(hapd, addr); + if (sta) + return 0; + + wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR + " - adding a new STA", MAC2STR(addr)); + sta = ap_sta_add(hapd, addr); + if (sta) { + hostapd_new_assoc_sta(hapd, sta, 0); + } else { + wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR, + MAC2STR(addr)); + return -1; + } + + return 0; +} + + +static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src, + const u8 *data, size_t data_len) +{ + struct hostapd_iface *iface = hapd->iface; + size_t j; + + for (j = 0; j < iface->num_bss; j++) { + if (ap_get_sta(iface->bss[j], src)) { + hapd = iface->bss[j]; + break; + } + } + + ieee802_1x_receive(hapd, src, data, data_len); +} + + +void wpa_supplicant_event(void *ctx, enum wpa_event_type event, + union wpa_event_data *data) +{ + struct hostapd_data *hapd = ctx; + + switch (event) { + case EVENT_MICHAEL_MIC_FAILURE: + michael_mic_failure(hapd, data->michael_mic_failure.src, 1); + break; + case EVENT_SCAN_RESULTS: + if (hapd->iface->scan_cb) + hapd->iface->scan_cb(hapd->iface); + break; +#ifdef CONFIG_IEEE80211R + case EVENT_FT_RRB_RX: + wpa_ft_rrb_rx(hapd->wpa_auth, data->ft_rrb_rx.src, + data->ft_rrb_rx.data, data->ft_rrb_rx.data_len); + break; +#endif /* CONFIG_IEEE80211R */ + case EVENT_WPS_BUTTON_PUSHED: + hostapd_wps_button_pushed(hapd); + break; +#ifdef NEED_AP_MLME + case EVENT_TX_STATUS: + switch (data->tx_status.type) { + case WLAN_FC_TYPE_MGMT: + hostapd_mgmt_tx_cb(hapd, data->tx_status.data, + data->tx_status.data_len, + data->tx_status.stype, + data->tx_status.ack); + break; + case WLAN_FC_TYPE_DATA: + hostapd_tx_status(hapd, data->tx_status.dst, + data->tx_status.data, + data->tx_status.data_len, + data->tx_status.ack); + break; + } + break; + case EVENT_RX_FROM_UNKNOWN: + hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.frame, + data->rx_from_unknown.len); + break; + case EVENT_RX_MGMT: + hostapd_mgmt_rx(hapd, &data->rx_mgmt); + break; +#endif /* NEED_AP_MLME */ + case EVENT_RX_PROBE_REQ: + hostapd_probe_req_rx(hapd, data->rx_probe_req.sa, + data->rx_probe_req.ie, + data->rx_probe_req.ie_len); + break; + case EVENT_NEW_STA: + hostapd_event_new_sta(hapd, data->new_sta.addr); + break; + case EVENT_EAPOL_RX: + hostapd_event_eapol_rx(hapd, data->eapol_rx.src, + data->eapol_rx.data, + data->eapol_rx.data_len); + break; + case EVENT_ASSOC: + hostapd_notif_assoc(hapd, data->assoc_info.addr, + data->assoc_info.req_ies, + data->assoc_info.req_ies_len); + break; + case EVENT_DISASSOC: + if (data) + hostapd_notif_disassoc(hapd, data->disassoc_info.addr); + break; + case EVENT_DEAUTH: + if (data) + hostapd_notif_disassoc(hapd, data->deauth_info.addr); + break; + default: + wpa_printf(MSG_DEBUG, "Unknown event %d", event); + break; + } +} + +#endif /* HOSTAPD */ diff --git a/contrib/wpa/src/ap/hostapd.c b/contrib/wpa/src/ap/hostapd.c new file mode 100644 index 000000000000..841f9c59c46b --- /dev/null +++ b/contrib/wpa/src/ap/hostapd.c @@ -0,0 +1,887 @@ +/* + * hostapd / Initialization and configuration + * Copyright (c) 2002-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "radius/radius_client.h" +#include "drivers/driver.h" +#include "hostapd.h" +#include "authsrv.h" +#include "sta_info.h" +#include "accounting.h" +#include "ap_list.h" +#include "beacon.h" +#include "iapp.h" +#include "ieee802_1x.h" +#include "ieee802_11_auth.h" +#include "vlan_init.h" +#include "wpa_auth.h" +#include "wps_hostapd.h" +#include "hw_features.h" +#include "wpa_auth_glue.h" +#include "ap_drv_ops.h" +#include "ap_config.h" + + +static int hostapd_flush_old_stations(struct hostapd_data *hapd); +static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd); + +extern int wpa_debug_level; + + +int hostapd_reload_config(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + struct hostapd_config *newconf, *oldconf; + size_t j; + + if (iface->config_read_cb == NULL) + return -1; + newconf = iface->config_read_cb(iface->config_fname); + if (newconf == NULL) + return -1; + + /* + * Deauthenticate all stations since the new configuration may not + * allow them to use the BSS anymore. + */ + for (j = 0; j < iface->num_bss; j++) + hostapd_flush_old_stations(iface->bss[j]); + +#ifndef CONFIG_NO_RADIUS + /* TODO: update dynamic data based on changed configuration + * items (e.g., open/close sockets, etc.) */ + radius_client_flush(hapd->radius, 0); +#endif /* CONFIG_NO_RADIUS */ + + oldconf = hapd->iconf; + hapd->iconf = newconf; + hapd->conf = &newconf->bss[0]; + iface->conf = newconf; + + if (hostapd_setup_wpa_psk(hapd->conf)) { + wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK " + "after reloading configuration"); + } + + if (hapd->conf->ieee802_1x || hapd->conf->wpa) + hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 1); + else + hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 0); + + if (hapd->conf->wpa && hapd->wpa_auth == NULL) + hostapd_setup_wpa(hapd); + else if (hapd->conf->wpa) { + const u8 *wpa_ie; + size_t wpa_ie_len; + hostapd_reconfig_wpa(hapd); + wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); + if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) + wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " + "the kernel driver."); + } else if (hapd->wpa_auth) { + wpa_deinit(hapd->wpa_auth); + hapd->wpa_auth = NULL; + hostapd_set_privacy(hapd, 0); + hostapd_setup_encryption(hapd->conf->iface, hapd); + hostapd_set_generic_elem(hapd, (u8 *) "", 0); + } + + ieee802_11_set_beacon(hapd); + hostapd_update_wps(hapd); + + if (hapd->conf->ssid.ssid_set && + hostapd_set_ssid(hapd, (u8 *) hapd->conf->ssid.ssid, + hapd->conf->ssid.ssid_len)) { + wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); + /* try to continue */ + } + + hostapd_config_free(oldconf); + + wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface); + + return 0; +} + + +static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd, + char *ifname) +{ + int i; + + for (i = 0; i < NUM_WEP_KEYS; i++) { + if (hapd->drv.set_key(ifname, hapd, WPA_ALG_NONE, NULL, i, + i == 0 ? 1 : 0, NULL, 0, NULL, 0)) { + wpa_printf(MSG_DEBUG, "Failed to clear default " + "encryption keys (ifname=%s keyidx=%d)", + ifname, i); + } + } +#ifdef CONFIG_IEEE80211W + if (hapd->conf->ieee80211w) { + for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) { + if (hapd->drv.set_key(ifname, hapd, WPA_ALG_NONE, NULL, + i, i == 0 ? 1 : 0, NULL, 0, + NULL, 0)) { + wpa_printf(MSG_DEBUG, "Failed to clear " + "default mgmt encryption keys " + "(ifname=%s keyidx=%d)", ifname, i); + } + } + } +#endif /* CONFIG_IEEE80211W */ +} + + +static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd) +{ + hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface); + return 0; +} + + +static int hostapd_broadcast_wep_set(struct hostapd_data *hapd) +{ + int errors = 0, idx; + struct hostapd_ssid *ssid = &hapd->conf->ssid; + + idx = ssid->wep.idx; + if (ssid->wep.default_len && + hapd->drv.set_key(hapd->conf->iface, + hapd, WPA_ALG_WEP, NULL, idx, + idx == ssid->wep.idx, + NULL, 0, ssid->wep.key[idx], + ssid->wep.len[idx])) { + wpa_printf(MSG_WARNING, "Could not set WEP encryption."); + errors++; + } + + if (ssid->dyn_vlan_keys) { + size_t i; + for (i = 0; i <= ssid->max_dyn_vlan_keys; i++) { + const char *ifname; + struct hostapd_wep_keys *key = ssid->dyn_vlan_keys[i]; + if (key == NULL) + continue; + ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, + i); + if (ifname == NULL) + continue; + + idx = key->idx; + if (hapd->drv.set_key(ifname, hapd, WPA_ALG_WEP, NULL, + idx, idx == key->idx, NULL, 0, + key->key[idx], key->len[idx])) { + wpa_printf(MSG_WARNING, "Could not set " + "dynamic VLAN WEP encryption."); + errors++; + } + } + } + + return errors; +} + +/** + * hostapd_cleanup - Per-BSS cleanup (deinitialization) + * @hapd: Pointer to BSS data + * + * This function is used to free all per-BSS data structures and resources. + * This gets called in a loop for each BSS between calls to + * hostapd_cleanup_iface_pre() and hostapd_cleanup_iface() when an interface + * is deinitialized. Most of the modules that are initialized in + * hostapd_setup_bss() are deinitialized here. + */ +static void hostapd_cleanup(struct hostapd_data *hapd) +{ + if (hapd->iface->ctrl_iface_deinit) + hapd->iface->ctrl_iface_deinit(hapd); + + iapp_deinit(hapd->iapp); + hapd->iapp = NULL; + accounting_deinit(hapd); + hostapd_deinit_wpa(hapd); + vlan_deinit(hapd); + hostapd_acl_deinit(hapd); +#ifndef CONFIG_NO_RADIUS + radius_client_deinit(hapd->radius); + hapd->radius = NULL; +#endif /* CONFIG_NO_RADIUS */ + + hostapd_deinit_wps(hapd); + + authsrv_deinit(hapd); + + if (hapd->interface_added && + hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) { + wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s", + hapd->conf->iface); + } + + os_free(hapd->probereq_cb); + hapd->probereq_cb = NULL; +} + + +/** + * hostapd_cleanup_iface_pre - Preliminary per-interface cleanup + * @iface: Pointer to interface data + * + * This function is called before per-BSS data structures are deinitialized + * with hostapd_cleanup(). + */ +static void hostapd_cleanup_iface_pre(struct hostapd_iface *iface) +{ +} + + +/** + * hostapd_cleanup_iface - Complete per-interface cleanup + * @iface: Pointer to interface data + * + * This function is called after per-BSS data structures are deinitialized + * with hostapd_cleanup(). + */ +static void hostapd_cleanup_iface(struct hostapd_iface *iface) +{ + hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); + iface->hw_features = NULL; + os_free(iface->current_rates); + iface->current_rates = NULL; + ap_list_deinit(iface); + hostapd_config_free(iface->conf); + iface->conf = NULL; + + os_free(iface->config_fname); + os_free(iface->bss); + os_free(iface); +} + + +static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd) +{ + int i; + + hostapd_broadcast_wep_set(hapd); + + if (hapd->conf->ssid.wep.default_len) { + hostapd_set_privacy(hapd, 1); + return 0; + } + + for (i = 0; i < 4; i++) { + if (hapd->conf->ssid.wep.key[i] && + hapd->drv.set_key(iface, hapd, WPA_ALG_WEP, NULL, i, + i == hapd->conf->ssid.wep.idx, NULL, 0, + hapd->conf->ssid.wep.key[i], + hapd->conf->ssid.wep.len[i])) { + wpa_printf(MSG_WARNING, "Could not set WEP " + "encryption."); + return -1; + } + if (hapd->conf->ssid.wep.key[i] && + i == hapd->conf->ssid.wep.idx) + hostapd_set_privacy(hapd, 1); + } + + return 0; +} + + +static int hostapd_flush_old_stations(struct hostapd_data *hapd) +{ + int ret = 0; + + if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL) + return 0; + + wpa_printf(MSG_DEBUG, "Flushing old station entries"); + if (hostapd_flush(hapd)) { + wpa_printf(MSG_WARNING, "Could not connect to kernel driver."); + ret = -1; + } + wpa_printf(MSG_DEBUG, "Deauthenticate all stations"); + + /* New Prism2.5/3 STA firmware versions seem to have issues with this + * broadcast deauth frame. This gets the firmware in odd state where + * nothing works correctly, so let's skip sending this for the hostap + * driver. */ + if (hapd->driver && os_strcmp(hapd->driver->name, "hostap") != 0) { + u8 addr[ETH_ALEN]; + os_memset(addr, 0xff, ETH_ALEN); + hapd->drv.sta_deauth(hapd, addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + } + + return ret; +} + + +/** + * hostapd_validate_bssid_configuration - Validate BSSID configuration + * @iface: Pointer to interface data + * Returns: 0 on success, -1 on failure + * + * This function is used to validate that the configured BSSIDs are valid. + */ +static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface) +{ + u8 mask[ETH_ALEN] = { 0 }; + struct hostapd_data *hapd = iface->bss[0]; + unsigned int i = iface->conf->num_bss, bits = 0, j; + int res; + int auto_addr = 0; + + if (hostapd_drv_none(hapd)) + return 0; + + /* Generate BSSID mask that is large enough to cover the BSSIDs. */ + + /* Determine the bits necessary to cover the number of BSSIDs. */ + for (i--; i; i >>= 1) + bits++; + + /* Determine the bits necessary to any configured BSSIDs, + if they are higher than the number of BSSIDs. */ + for (j = 0; j < iface->conf->num_bss; j++) { + if (hostapd_mac_comp_empty(iface->conf->bss[j].bssid) == 0) { + if (j) + auto_addr++; + continue; + } + + for (i = 0; i < ETH_ALEN; i++) { + mask[i] |= + iface->conf->bss[j].bssid[i] ^ + hapd->own_addr[i]; + } + } + + if (!auto_addr) + goto skip_mask_ext; + + for (i = 0; i < ETH_ALEN && mask[i] == 0; i++) + ; + j = 0; + if (i < ETH_ALEN) { + j = (5 - i) * 8; + + while (mask[i] != 0) { + mask[i] >>= 1; + j++; + } + } + + if (bits < j) + bits = j; + + if (bits > 40) { + wpa_printf(MSG_ERROR, "Too many bits in the BSSID mask (%u)", + bits); + return -1; + } + + os_memset(mask, 0xff, ETH_ALEN); + j = bits / 8; + for (i = 5; i > 5 - j; i--) + mask[i] = 0; + j = bits % 8; + while (j--) + mask[i] <<= 1; + +skip_mask_ext: + wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)", + (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits); + + res = hostapd_valid_bss_mask(hapd, hapd->own_addr, mask); + if (res == 0) + return 0; + + if (res < 0) { + wpa_printf(MSG_ERROR, "Driver did not accept BSSID mask " + MACSTR " for start address " MACSTR ".", + MAC2STR(mask), MAC2STR(hapd->own_addr)); + return -1; + } + + if (!auto_addr) + return 0; + + for (i = 0; i < ETH_ALEN; i++) { + if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) { + wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR + " for start address " MACSTR ".", + MAC2STR(mask), MAC2STR(hapd->own_addr)); + wpa_printf(MSG_ERROR, "Start address must be the " + "first address in the block (i.e., addr " + "AND mask == addr)."); + return -1; + } + } + + return 0; +} + + +static int mac_in_conf(struct hostapd_config *conf, const void *a) +{ + size_t i; + + for (i = 0; i < conf->num_bss; i++) { + if (hostapd_mac_comp(conf->bss[i].bssid, a) == 0) { + return 1; + } + } + + return 0; +} + + + + +/** + * hostapd_setup_bss - Per-BSS setup (initialization) + * @hapd: Pointer to BSS data + * @first: Whether this BSS is the first BSS of an interface + * + * This function is used to initialize all per-BSS data structures and + * resources. This gets called in a loop for each BSS when an interface is + * initialized. Most of the modules that are initialized here will be + * deinitialized in hostapd_cleanup(). + */ +static int hostapd_setup_bss(struct hostapd_data *hapd, int first) +{ + struct hostapd_bss_config *conf = hapd->conf; + u8 ssid[HOSTAPD_MAX_SSID_LEN + 1]; + int ssid_len, set_ssid; + char force_ifname[IFNAMSIZ]; + u8 if_addr[ETH_ALEN]; + + if (!first) { + if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) { + /* Allocate the next available BSSID. */ + do { + inc_byte_array(hapd->own_addr, ETH_ALEN); + } while (mac_in_conf(hapd->iconf, hapd->own_addr)); + } else { + /* Allocate the configured BSSID. */ + os_memcpy(hapd->own_addr, hapd->conf->bssid, ETH_ALEN); + + if (hostapd_mac_comp(hapd->own_addr, + hapd->iface->bss[0]->own_addr) == + 0) { + wpa_printf(MSG_ERROR, "BSS '%s' may not have " + "BSSID set to the MAC address of " + "the radio", hapd->conf->iface); + return -1; + } + } + + hapd->interface_added = 1; + if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS, + hapd->conf->iface, hapd->own_addr, hapd, + &hapd->drv_priv, force_ifname, if_addr)) { + wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID=" + MACSTR ")", MAC2STR(hapd->own_addr)); + return -1; + } + } + + hostapd_flush_old_stations(hapd); + hostapd_set_privacy(hapd, 0); + + hostapd_broadcast_wep_clear(hapd); + if (hostapd_setup_encryption(hapd->conf->iface, hapd)) + return -1; + + /* + * Fetch the SSID from the system and use it or, + * if one was specified in the config file, verify they + * match. + */ + ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid)); + if (ssid_len < 0) { + wpa_printf(MSG_ERROR, "Could not read SSID from system"); + return -1; + } + if (conf->ssid.ssid_set) { + /* + * If SSID is specified in the config file and it differs + * from what is being used then force installation of the + * new SSID. + */ + set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len || + os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0); + } else { + /* + * No SSID in the config file; just use the one we got + * from the system. + */ + set_ssid = 0; + conf->ssid.ssid_len = ssid_len; + os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len); + conf->ssid.ssid[conf->ssid.ssid_len] = '\0'; + } + + if (!hostapd_drv_none(hapd)) { + wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR + " and ssid '%s'", + hapd->conf->iface, MAC2STR(hapd->own_addr), + hapd->conf->ssid.ssid); + } + + if (hostapd_setup_wpa_psk(conf)) { + wpa_printf(MSG_ERROR, "WPA-PSK setup failed."); + return -1; + } + + /* Set SSID for the kernel driver (to be used in beacon and probe + * response frames) */ + if (set_ssid && hostapd_set_ssid(hapd, (u8 *) conf->ssid.ssid, + conf->ssid.ssid_len)) { + wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); + return -1; + } + + if (wpa_debug_level == MSG_MSGDUMP) + conf->radius->msg_dumps = 1; +#ifndef CONFIG_NO_RADIUS + hapd->radius = radius_client_init(hapd, conf->radius); + if (hapd->radius == NULL) { + wpa_printf(MSG_ERROR, "RADIUS client initialization failed."); + return -1; + } +#endif /* CONFIG_NO_RADIUS */ + + if (hostapd_acl_init(hapd)) { + wpa_printf(MSG_ERROR, "ACL initialization failed."); + return -1; + } + if (hostapd_init_wps(hapd, conf)) + return -1; + + if (authsrv_init(hapd) < 0) + return -1; + + if (ieee802_1x_init(hapd)) { + wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed."); + return -1; + } + + if (hapd->conf->wpa && hostapd_setup_wpa(hapd)) + return -1; + + if (accounting_init(hapd)) { + wpa_printf(MSG_ERROR, "Accounting initialization failed."); + return -1; + } + + if (hapd->conf->ieee802_11f && + (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) { + wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization " + "failed."); + return -1; + } + + if (hapd->iface->ctrl_iface_init && + hapd->iface->ctrl_iface_init(hapd)) { + wpa_printf(MSG_ERROR, "Failed to setup control interface"); + return -1; + } + + if (!hostapd_drv_none(hapd) && vlan_init(hapd)) { + wpa_printf(MSG_ERROR, "VLAN initialization failed."); + return -1; + } + + ieee802_11_set_beacon(hapd); + + return 0; +} + + +static void hostapd_tx_queue_params(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + int i; + struct hostapd_tx_queue_params *p; + + for (i = 0; i < NUM_TX_QUEUES; i++) { + p = &iface->conf->tx_queue[i]; + + if (!p->configured) + continue; + + if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin, + p->cwmax, p->burst)) { + wpa_printf(MSG_DEBUG, "Failed to set TX queue " + "parameters for queue %d.", i); + /* Continue anyway */ + } + } +} + + +static int setup_interface(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + size_t i; + char country[4]; + + /* + * Make sure that all BSSes get configured with a pointer to the same + * driver interface. + */ + for (i = 1; i < iface->num_bss; i++) { + iface->bss[i]->driver = hapd->driver; + iface->bss[i]->drv_priv = hapd->drv_priv; + } + + if (hostapd_validate_bssid_configuration(iface)) + return -1; + + if (hapd->iconf->country[0] && hapd->iconf->country[1]) { + os_memcpy(country, hapd->iconf->country, 3); + country[3] = '\0'; + if (hostapd_set_country(hapd, country) < 0) { + wpa_printf(MSG_ERROR, "Failed to set country code"); + return -1; + } + } + + if (hostapd_get_hw_features(iface)) { + /* Not all drivers support this yet, so continue without hw + * feature data. */ + } else { + int ret = hostapd_select_hw_mode(iface); + if (ret < 0) { + wpa_printf(MSG_ERROR, "Could not select hw_mode and " + "channel. (%d)", ret); + return -1; + } + ret = hostapd_check_ht_capab(iface); + if (ret < 0) + return -1; + if (ret == 1) { + wpa_printf(MSG_DEBUG, "Interface initialization will " + "be completed in a callback"); + return 0; + } + } + return hostapd_setup_interface_complete(iface, 0); +} + + +int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err) +{ + struct hostapd_data *hapd = iface->bss[0]; + size_t j; + u8 *prev_addr; + + if (err) { + wpa_printf(MSG_ERROR, "Interface initialization failed"); + eloop_terminate(); + return -1; + } + + wpa_printf(MSG_DEBUG, "Completing interface initialization"); + if (hapd->iconf->channel) { + iface->freq = hostapd_hw_get_freq(hapd, hapd->iconf->channel); + wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d " + "Frequency: %d MHz", + hostapd_hw_mode_txt(hapd->iconf->hw_mode), + hapd->iconf->channel, iface->freq); + + if (hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq, + hapd->iconf->channel, + hapd->iconf->ieee80211n, + hapd->iconf->secondary_channel)) { + wpa_printf(MSG_ERROR, "Could not set channel for " + "kernel driver"); + return -1; + } + } + + if (hapd->iconf->rts_threshold > -1 && + hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) { + wpa_printf(MSG_ERROR, "Could not set RTS threshold for " + "kernel driver"); + return -1; + } + + if (hapd->iconf->fragm_threshold > -1 && + hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) { + wpa_printf(MSG_ERROR, "Could not set fragmentation threshold " + "for kernel driver"); + return -1; + } + + prev_addr = hapd->own_addr; + + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + if (j) + os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); + if (hostapd_setup_bss(hapd, j == 0)) + return -1; + if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) + prev_addr = hapd->own_addr; + } + + hostapd_tx_queue_params(iface); + + ap_list_init(iface); + + if (hostapd_driver_commit(hapd) < 0) { + wpa_printf(MSG_ERROR, "%s: Failed to commit driver " + "configuration", __func__); + return -1; + } + + wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", + iface->bss[0]->conf->iface); + + return 0; +} + + +/** + * hostapd_setup_interface - Setup of an interface + * @iface: Pointer to interface data. + * Returns: 0 on success, -1 on failure + * + * Initializes the driver interface, validates the configuration, + * and sets driver parameters based on the configuration. + * Flushes old stations, sets the channel, encryption, + * beacons, and WDS links based on the configuration. + */ +int hostapd_setup_interface(struct hostapd_iface *iface) +{ + int ret; + + ret = setup_interface(iface); + if (ret) { + wpa_printf(MSG_ERROR, "%s: Unable to setup interface.", + iface->bss[0]->conf->iface); + return -1; + } + + return 0; +} + + +/** + * hostapd_alloc_bss_data - Allocate and initialize per-BSS data + * @hapd_iface: Pointer to interface data + * @conf: Pointer to per-interface configuration + * @bss: Pointer to per-BSS configuration for this BSS + * Returns: Pointer to allocated BSS data + * + * This function is used to allocate per-BSS data structure. This data will be + * freed after hostapd_cleanup() is called for it during interface + * deinitialization. + */ +struct hostapd_data * +hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, + struct hostapd_config *conf, + struct hostapd_bss_config *bss) +{ + struct hostapd_data *hapd; + + hapd = os_zalloc(sizeof(*hapd)); + if (hapd == NULL) + return NULL; + + hostapd_set_driver_ops(&hapd->drv); + hapd->new_assoc_sta_cb = hostapd_new_assoc_sta; + hapd->iconf = conf; + hapd->conf = bss; + hapd->iface = hapd_iface; + hapd->driver = hapd->iconf->driver; + + return hapd; +} + + +void hostapd_interface_deinit(struct hostapd_iface *iface) +{ + size_t j; + + if (iface == NULL) + return; + + hostapd_cleanup_iface_pre(iface); + for (j = 0; j < iface->num_bss; j++) { + struct hostapd_data *hapd = iface->bss[j]; + hostapd_free_stas(hapd); + hostapd_flush_old_stations(hapd); + hostapd_cleanup(hapd); + } +} + + +void hostapd_interface_free(struct hostapd_iface *iface) +{ + size_t j; + for (j = 0; j < iface->num_bss; j++) + os_free(iface->bss[j]); + hostapd_cleanup_iface(iface); +} + + +/** + * hostapd_new_assoc_sta - Notify that a new station associated with the AP + * @hapd: Pointer to BSS data + * @sta: Pointer to the associated STA data + * @reassoc: 1 to indicate this was a re-association; 0 = first association + * + * This function will be called whenever a station associates with the AP. It + * can be called from ieee802_11.c for drivers that export MLME to hostapd and + * from drv_callbacks.c based on driver events for drivers that take care of + * management frames (IEEE 802.11 authentication and association) internally. + */ +void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, + int reassoc) +{ + if (hapd->tkip_countermeasures) { + hapd->drv.sta_deauth(hapd, sta->addr, + WLAN_REASON_MICHAEL_MIC_FAILURE); + return; + } + + hostapd_prune_associations(hapd, sta->addr); + + /* IEEE 802.11F (IAPP) */ + if (hapd->conf->ieee802_11f) + iapp_new_station(hapd->iapp, sta); + + /* Start accounting here, if IEEE 802.1X and WPA are not used. + * IEEE 802.1X/WPA code will start accounting after the station has + * been authorized. */ + if (!hapd->conf->ieee802_1x && !hapd->conf->wpa) + accounting_sta_start(hapd, sta); + + /* Start IEEE 802.1X authentication process for new stations */ + ieee802_1x_new_station(hapd, sta); + if (reassoc) { + if (sta->auth_alg != WLAN_AUTH_FT && + !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) + wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH); + } else + wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm); +} diff --git a/contrib/wpa/src/ap/hostapd.h b/contrib/wpa/src/ap/hostapd.h new file mode 100644 index 000000000000..d0d67c8228a4 --- /dev/null +++ b/contrib/wpa/src/ap/hostapd.h @@ -0,0 +1,276 @@ +/* + * hostapd / Initialization and configuration + * Copyright (c) 2002-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef HOSTAPD_H +#define HOSTAPD_H + +#include "common/defs.h" + +struct wpa_driver_ops; +struct wpa_ctrl_dst; +struct radius_server_data; +struct upnp_wps_device_sm; +struct hapd_interfaces; +struct hostapd_data; +struct sta_info; +struct hostap_sta_driver_data; +struct ieee80211_ht_capabilities; +struct full_dynamic_vlan; + +struct hostapd_probereq_cb { + int (*cb)(void *ctx, const u8 *sa, const u8 *ie, size_t ie_len); + void *ctx; +}; + +#define HOSTAPD_RATE_BASIC 0x00000001 + +struct hostapd_rate_data { + int rate; /* rate in 100 kbps */ + int flags; /* HOSTAPD_RATE_ flags */ +}; + +struct hostapd_frame_info { + u32 channel; + u32 datarate; + u32 ssi_signal; +}; + + +struct hostapd_driver_ops { + int (*set_ap_wps_ie)(struct hostapd_data *hapd); + int (*send_mgmt_frame)(struct hostapd_data *hapd, const void *msg, + size_t len); + int (*send_eapol)(struct hostapd_data *hapd, const u8 *addr, + const u8 *data, size_t data_len, int encrypt); + int (*set_authorized)(struct hostapd_data *hapd, struct sta_info *sta, + int authorized); + int (*set_key)(const char *ifname, struct hostapd_data *hapd, + enum wpa_alg alg, const u8 *addr, int key_idx, + int set_tx, const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len); + int (*read_sta_data)(struct hostapd_data *hapd, + struct hostap_sta_driver_data *data, + const u8 *addr); + int (*sta_clear_stats)(struct hostapd_data *hapd, const u8 *addr); + int (*set_sta_flags)(struct hostapd_data *hapd, struct sta_info *sta); + int (*set_drv_ieee8021x)(struct hostapd_data *hapd, const char *ifname, + int enabled); + int (*set_radius_acl_auth)(struct hostapd_data *hapd, + const u8 *mac, int accepted, + u32 session_timeout); + int (*set_radius_acl_expire)(struct hostapd_data *hapd, + const u8 *mac); + int (*set_bss_params)(struct hostapd_data *hapd, int use_protection); + int (*set_beacon)(struct hostapd_data *hapd, + const u8 *head, size_t head_len, + const u8 *tail, size_t tail_len, int dtim_period, + int beacon_int); + int (*vlan_if_add)(struct hostapd_data *hapd, const char *ifname); + int (*vlan_if_remove)(struct hostapd_data *hapd, const char *ifname); + int (*set_wds_sta)(struct hostapd_data *hapd, const u8 *addr, int aid, + int val); + int (*set_sta_vlan)(const char *ifname, struct hostapd_data *hapd, + const u8 *addr, int vlan_id); + int (*get_inact_sec)(struct hostapd_data *hapd, const u8 *addr); + int (*sta_deauth)(struct hostapd_data *hapd, const u8 *addr, + int reason); + int (*sta_disassoc)(struct hostapd_data *hapd, const u8 *addr, + int reason); + int (*sta_add)(struct hostapd_data *hapd, + const u8 *addr, u16 aid, u16 capability, + const u8 *supp_rates, size_t supp_rates_len, + u16 listen_interval, + const struct ieee80211_ht_capabilities *ht_capab); + int (*sta_remove)(struct hostapd_data *hapd, const u8 *addr); + int (*set_countermeasures)(struct hostapd_data *hapd, int enabled); +}; + +/** + * struct hostapd_data - hostapd per-BSS data structure + */ +struct hostapd_data { + struct hostapd_iface *iface; + struct hostapd_config *iconf; + struct hostapd_bss_config *conf; + int interface_added; /* virtual interface added for this BSS */ + + u8 own_addr[ETH_ALEN]; + + int num_sta; /* number of entries in sta_list */ + struct sta_info *sta_list; /* STA info list head */ +#define STA_HASH_SIZE 256 +#define STA_HASH(sta) (sta[5]) + struct sta_info *sta_hash[STA_HASH_SIZE]; + + /* + * Bitfield for indicating which AIDs are allocated. Only AID values + * 1-2007 are used and as such, the bit at index 0 corresponds to AID + * 1. + */ +#define AID_WORDS ((2008 + 31) / 32) + u32 sta_aid[AID_WORDS]; + + const struct wpa_driver_ops *driver; + void *drv_priv; + struct hostapd_driver_ops drv; + + void (*new_assoc_sta_cb)(struct hostapd_data *hapd, + struct sta_info *sta, int reassoc); + + void *msg_ctx; /* ctx for wpa_msg() calls */ + + struct radius_client_data *radius; + u32 acct_session_id_hi, acct_session_id_lo; + + struct iapp_data *iapp; + + struct hostapd_cached_radius_acl *acl_cache; + struct hostapd_acl_query_data *acl_queries; + + struct wpa_authenticator *wpa_auth; + struct eapol_authenticator *eapol_auth; + + struct rsn_preauth_interface *preauth_iface; + time_t michael_mic_failure; + int michael_mic_failures; + int tkip_countermeasures; + + int ctrl_sock; + struct wpa_ctrl_dst *ctrl_dst; + + void *ssl_ctx; + void *eap_sim_db_priv; + struct radius_server_data *radius_srv; + + int parameter_set_count; + +#ifdef CONFIG_FULL_DYNAMIC_VLAN + struct full_dynamic_vlan *full_dynamic_vlan; +#endif /* CONFIG_FULL_DYNAMIC_VLAN */ + + struct l2_packet_data *l2; + struct wps_context *wps; + + struct wpabuf *wps_beacon_ie; + struct wpabuf *wps_probe_resp_ie; +#ifdef CONFIG_WPS + unsigned int ap_pin_failures; + struct upnp_wps_device_sm *wps_upnp; + unsigned int ap_pin_lockout_time; +#endif /* CONFIG_WPS */ + + struct hostapd_probereq_cb *probereq_cb; + size_t num_probereq_cb; + + void (*public_action_cb)(void *ctx, const u8 *buf, size_t len, + int freq); + void *public_action_cb_ctx; + + void (*wps_reg_success_cb)(void *ctx, const u8 *mac_addr, + const u8 *uuid_e); + void *wps_reg_success_cb_ctx; +}; + + +/** + * struct hostapd_iface - hostapd per-interface data structure + */ +struct hostapd_iface { + struct hapd_interfaces *interfaces; + void *owner; + int (*reload_config)(struct hostapd_iface *iface); + struct hostapd_config * (*config_read_cb)(const char *config_fname); + char *config_fname; + struct hostapd_config *conf; + + size_t num_bss; + struct hostapd_data **bss; + + int num_ap; /* number of entries in ap_list */ + struct ap_info *ap_list; /* AP info list head */ + struct ap_info *ap_hash[STA_HASH_SIZE]; + struct ap_info *ap_iter_list; + + struct hostapd_hw_modes *hw_features; + int num_hw_features; + struct hostapd_hw_modes *current_mode; + /* Rates that are currently used (i.e., filtered copy of + * current_mode->channels */ + int num_rates; + struct hostapd_rate_data *current_rates; + int freq; + + u16 hw_flags; + + /* Number of associated Non-ERP stations (i.e., stations using 802.11b + * in 802.11g BSS) */ + int num_sta_non_erp; + + /* Number of associated stations that do not support Short Slot Time */ + int num_sta_no_short_slot_time; + + /* Number of associated stations that do not support Short Preamble */ + int num_sta_no_short_preamble; + + int olbc; /* Overlapping Legacy BSS Condition */ + + /* Number of HT associated stations that do not support greenfield */ + int num_sta_ht_no_gf; + + /* Number of associated non-HT stations */ + int num_sta_no_ht; + + /* Number of HT associated stations 20 MHz */ + int num_sta_ht_20mhz; + + /* Overlapping BSS information */ + int olbc_ht; + + u16 ht_op_mode; + void (*scan_cb)(struct hostapd_iface *iface); + + int (*ctrl_iface_init)(struct hostapd_data *hapd); + void (*ctrl_iface_deinit)(struct hostapd_data *hapd); + + int (*for_each_interface)(struct hapd_interfaces *interfaces, + int (*cb)(struct hostapd_iface *iface, + void *ctx), void *ctx); +}; + +/* hostapd.c */ +int hostapd_reload_config(struct hostapd_iface *iface); +struct hostapd_data * +hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, + struct hostapd_config *conf, + struct hostapd_bss_config *bss); +int hostapd_setup_interface(struct hostapd_iface *iface); +int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err); +void hostapd_interface_deinit(struct hostapd_iface *iface); +void hostapd_interface_free(struct hostapd_iface *iface); +void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, + int reassoc); + +/* utils.c */ +int hostapd_register_probereq_cb(struct hostapd_data *hapd, + int (*cb)(void *ctx, const u8 *sa, + const u8 *ie, size_t ie_len), + void *ctx); +void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr); + +/* drv_callbacks.c (TODO: move to somewhere else?) */ +int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, + const u8 *ie, size_t ielen); +void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr); + +#endif /* HOSTAPD_H */ diff --git a/contrib/wpa/hostapd/hw_features.c b/contrib/wpa/src/ap/hw_features.c similarity index 63% rename from contrib/wpa/hostapd/hw_features.c rename to contrib/wpa/src/ap/hw_features.c index 1d6299e625ed..0159c725180e 100644 --- a/contrib/wpa/hostapd/hw_features.c +++ b/contrib/wpa/src/ap/hw_features.c @@ -2,7 +2,7 @@ * hostapd / Hardware feature query and different modes * Copyright 2002-2003, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. - * Copyright (c) 2008, Jouni Malinen + * Copyright (c) 2008-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -14,12 +14,17 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "drivers/driver.h" #include "hostapd.h" +#include "ap_config.h" +#include "ap_drv_ops.h" #include "hw_features.h" -#include "driver.h" -#include "config.h" void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, @@ -131,7 +136,7 @@ static int hostapd_prepare_rates(struct hostapd_data *hapd, hapd->iface->num_rates = 0; hapd->iface->current_rates = - os_malloc(mode->num_rates * sizeof(struct hostapd_rate_data)); + os_zalloc(mode->num_rates * sizeof(struct hostapd_rate_data)); if (!hapd->iface->current_rates) { wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " "table."); @@ -143,17 +148,15 @@ static int hostapd_prepare_rates(struct hostapd_data *hapd, if (hapd->iconf->supported_rates && !hostapd_rate_found(hapd->iconf->supported_rates, - mode->rates[i].rate)) + mode->rates[i])) continue; rate = &hapd->iface->current_rates[hapd->iface->num_rates]; - os_memcpy(rate, &mode->rates[i], - sizeof(struct hostapd_rate_data)); + rate->rate = mode->rates[i]; if (hostapd_rate_found(basic_rates, rate->rate)) { rate->flags |= HOSTAPD_RATE_BASIC; num_basic_rates++; - } else - rate->flags &= ~HOSTAPD_RATE_BASIC; + } wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", hapd->iface->num_rates, rate->rate, rate->flags); hapd->iface->num_rates++; @@ -236,6 +239,245 @@ static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) } +static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface) +{ + if (iface->conf->secondary_channel > 0) { + iface->conf->channel += 4; + iface->conf->secondary_channel = -1; + } else { + iface->conf->channel -= 4; + iface->conf->secondary_channel = 1; + } +} + + +static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss, + int *pri_chan, int *sec_chan) +{ + struct ieee80211_ht_operation *oper; + struct ieee802_11_elems elems; + + *pri_chan = *sec_chan = 0; + + ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0); + if (elems.ht_operation && + elems.ht_operation_len >= sizeof(*oper)) { + oper = (struct ieee80211_ht_operation *) elems.ht_operation; + *pri_chan = oper->control_chan; + if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) { + if (oper->ht_param & + HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE) + *sec_chan = *pri_chan + 4; + else if (oper->ht_param & + HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW) + *sec_chan = *pri_chan - 4; + } + } +} + + +static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface, + struct wpa_scan_results *scan_res) +{ + int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss; + int bss_pri_chan, bss_sec_chan; + size_t i; + int match; + + pri_chan = iface->conf->channel; + sec_chan = iface->conf->secondary_channel * 4; + pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan); + if (iface->conf->secondary_channel > 0) + sec_freq = pri_freq + 20; + else + sec_freq = pri_freq - 20; + + /* + * Switch PRI/SEC channels if Beacons were detected on selected SEC + * channel, but not on selected PRI channel. + */ + pri_bss = sec_bss = 0; + for (i = 0; i < scan_res->num; i++) { + struct wpa_scan_res *bss = scan_res->res[i]; + if (bss->freq == pri_freq) + pri_bss++; + else if (bss->freq == sec_freq) + sec_bss++; + } + if (sec_bss && !pri_bss) { + wpa_printf(MSG_INFO, "Switch own primary and secondary " + "channel to get secondary channel with no Beacons " + "from other BSSes"); + ieee80211n_switch_pri_sec(iface); + } + + /* + * Match PRI/SEC channel with any existing HT40 BSS on the same + * channels that we are about to use (if already mixed order in + * existing BSSes, use own preference). + */ + match = 0; + for (i = 0; i < scan_res->num; i++) { + struct wpa_scan_res *bss = scan_res->res[i]; + ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan); + if (pri_chan == bss_pri_chan && + sec_chan == bss_sec_chan) { + match = 1; + break; + } + } + if (!match) { + for (i = 0; i < scan_res->num; i++) { + struct wpa_scan_res *bss = scan_res->res[i]; + ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, + &bss_sec_chan); + if (pri_chan == bss_sec_chan && + sec_chan == bss_pri_chan) { + wpa_printf(MSG_INFO, "Switch own primary and " + "secondary channel due to BSS " + "overlap with " MACSTR, + MAC2STR(bss->bssid)); + ieee80211n_switch_pri_sec(iface); + break; + } + } + } + + return 1; +} + + +static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface, + struct wpa_scan_results *scan_res) +{ + int pri_freq, sec_freq; + int affected_start, affected_end; + size_t i; + + pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); + if (iface->conf->secondary_channel > 0) + sec_freq = pri_freq + 20; + else + sec_freq = pri_freq - 20; + affected_start = (pri_freq + sec_freq) / 2 - 25; + affected_end = (pri_freq + sec_freq) / 2 + 25; + wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", + affected_start, affected_end); + for (i = 0; i < scan_res->num; i++) { + struct wpa_scan_res *bss = scan_res->res[i]; + int pri = bss->freq; + int sec = pri; + int sec_chan, pri_chan; + + ieee80211n_get_pri_sec_chan(bss, &pri_chan, &sec_chan); + + if (sec_chan) { + if (sec_chan < pri_chan) + sec = pri - 20; + else + sec = pri + 20; + } + + if ((pri < affected_start || pri > affected_end) && + (sec < affected_start || sec > affected_end)) + continue; /* not within affected channel range */ + + wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR + " freq=%d pri=%d sec=%d", + MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan); + + if (sec_chan) { + if (pri_freq != pri || sec_freq != sec) { + wpa_printf(MSG_DEBUG, "40 MHz pri/sec " + "mismatch with BSS " MACSTR + " <%d,%d> (chan=%d%c) vs. <%d,%d>", + MAC2STR(bss->bssid), + pri, sec, pri_chan, + sec > pri ? '+' : '-', + pri_freq, sec_freq); + return 0; + } + } + + /* TODO: 40 MHz intolerant */ + } + + return 1; +} + + +static void wpa_scan_results_free(struct wpa_scan_results *res) +{ + size_t i; + + if (res == NULL) + return; + + for (i = 0; i < res->num; i++) + os_free(res->res[i]); + os_free(res->res); + os_free(res); +} + + +static void ieee80211n_check_scan(struct hostapd_iface *iface) +{ + struct wpa_scan_results *scan_res; + int oper40; + + /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is + * allowed per IEEE 802.11n/D7.0, 11.14.3.2 */ + + iface->scan_cb = NULL; + + scan_res = hostapd_driver_get_scan_results(iface->bss[0]); + if (scan_res == NULL) { + hostapd_setup_interface_complete(iface, 1); + return; + } + + if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) + oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); + else + oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); + wpa_scan_results_free(scan_res); + + if (!oper40) { + wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " + "channel pri=%d sec=%d based on overlapping BSSes", + iface->conf->channel, + iface->conf->channel + + iface->conf->secondary_channel * 4); + iface->conf->secondary_channel = 0; + iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; + } + + hostapd_setup_interface_complete(iface, 0); +} + + +static int ieee80211n_check_40mhz(struct hostapd_iface *iface) +{ + struct wpa_driver_scan_params params; + + if (!iface->conf->secondary_channel) + return 0; /* HT40 not used */ + + wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " + "40 MHz channel"); + os_memset(¶ms, 0, sizeof(params)); + /* TODO: scan only the needed frequency */ + if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) { + wpa_printf(MSG_ERROR, "Failed to request a scan of " + "neighboring BSSes"); + return -1; + } + + iface->scan_cb = ieee80211n_check_scan; + return 1; +} + + static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) { u16 hw = iface->current_mode->ht_capab; @@ -335,9 +577,27 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) return 1; } + #endif /* CONFIG_IEEE80211N */ +int hostapd_check_ht_capab(struct hostapd_iface *iface) +{ +#ifdef CONFIG_IEEE80211N + int ret; + ret = ieee80211n_check_40mhz(iface); + if (ret) + return ret; + if (!ieee80211n_allowed_ht40_channel_pair(iface)) + return -1; + if (!ieee80211n_supported_ht_capab(iface)) + return -1; +#endif /* CONFIG_IEEE80211N */ + + return 0; +} + + /** * hostapd_select_hw_mode - Select the hardware mode * @iface: Pointer to interface data. @@ -348,7 +608,7 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) */ int hostapd_select_hw_mode(struct hostapd_iface *iface) { - int i, j, ok, ret; + int i, j, ok; if (iface->num_hw_features < 1) return -1; @@ -356,7 +616,7 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface) iface->current_mode = NULL; for (i = 0; i < iface->num_hw_features; i++) { struct hostapd_hw_modes *mode = &iface->hw_features[i]; - if (mode->mode == (int) iface->conf->hw_mode) { + if (mode->mode == iface->conf->hw_mode) { iface->current_mode = mode; break; } @@ -408,13 +668,6 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface) return -1; } -#ifdef CONFIG_IEEE80211N - if (!ieee80211n_allowed_ht40_channel_pair(iface)) - return -1; - if (!ieee80211n_supported_ht_capab(iface)) - return -1; -#endif /* CONFIG_IEEE80211N */ - if (hostapd_prepare_rates(iface->bss[0], iface->current_mode)) { wpa_printf(MSG_ERROR, "Failed to prepare rates table."); hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, @@ -423,23 +676,7 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface) return -1; } - ret = hostapd_passive_scan(iface->bss[0], 0, - iface->conf->passive_scan_mode, - iface->conf->passive_scan_interval, - iface->conf->passive_scan_listen, - NULL, NULL); - if (ret) { - if (ret == -1) { - wpa_printf(MSG_DEBUG, "Passive scanning not " - "supported"); - } else { - wpa_printf(MSG_ERROR, "Could not set passive " - "scanning: %s", strerror(ret)); - } - ret = 0; - } - - return ret; + return 0; } diff --git a/contrib/wpa/hostapd/hw_features.h b/contrib/wpa/src/ap/hw_features.h similarity index 50% rename from contrib/wpa/hostapd/hw_features.h rename to contrib/wpa/src/ap/hw_features.h index 7d43c89b6696..0295549fe1d3 100644 --- a/contrib/wpa/hostapd/hw_features.h +++ b/contrib/wpa/src/ap/hw_features.h @@ -16,41 +16,7 @@ #ifndef HW_FEATURES_H #define HW_FEATURES_H -#define HOSTAPD_CHAN_DISABLED 0x00000001 -#define HOSTAPD_CHAN_PASSIVE_SCAN 0x00000002 -#define HOSTAPD_CHAN_NO_IBSS 0x00000004 -#define HOSTAPD_CHAN_RADAR 0x00000008 - -struct hostapd_channel_data { - short chan; /* channel number (IEEE 802.11) */ - short freq; /* frequency in MHz */ - int flag; /* flag for hostapd use (HOSTAPD_CHAN_*) */ - u8 max_tx_power; /* maximum transmit power in dBm */ -}; - -#define HOSTAPD_RATE_ERP 0x00000001 -#define HOSTAPD_RATE_BASIC 0x00000002 -#define HOSTAPD_RATE_PREAMBLE2 0x00000004 -#define HOSTAPD_RATE_SUPPORTED 0x00000010 -#define HOSTAPD_RATE_OFDM 0x00000020 -#define HOSTAPD_RATE_CCK 0x00000040 -#define HOSTAPD_RATE_MANDATORY 0x00000100 - -struct hostapd_rate_data { - int rate; /* rate in 100 kbps */ - int flags; /* HOSTAPD_RATE_ flags */ -}; - -struct hostapd_hw_modes { - int mode; - int num_channels; - struct hostapd_channel_data *channels; - int num_rates; - struct hostapd_rate_data *rates; - u16 ht_capab; -}; - - +#ifdef NEED_AP_MLME void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, size_t num_hw_features); int hostapd_get_hw_features(struct hostapd_iface *iface); @@ -58,5 +24,39 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface); const char * hostapd_hw_mode_txt(int mode); int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan); int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq); +int hostapd_check_ht_capab(struct hostapd_iface *iface); +#else /* NEED_AP_MLME */ +static inline void +hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, + size_t num_hw_features) +{ +} + +static inline int hostapd_get_hw_features(struct hostapd_iface *iface) +{ + return -1; +} + +static inline int hostapd_select_hw_mode(struct hostapd_iface *iface) +{ + return -1; +} + +static inline const char * hostapd_hw_mode_txt(int mode) +{ + return NULL; +} + +static inline int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) +{ + return -1; +} + +static inline int hostapd_check_ht_capab(struct hostapd_iface *iface) +{ + return 0; +} + +#endif /* NEED_AP_MLME */ #endif /* HW_FEATURES_H */ diff --git a/contrib/wpa/hostapd/iapp.c b/contrib/wpa/src/ap/iapp.c similarity index 95% rename from contrib/wpa/hostapd/iapp.c rename to contrib/wpa/src/ap/iapp.c index 6d6dba8f7b9a..115d91e8ce30 100644 --- a/contrib/wpa/hostapd/iapp.c +++ b/contrib/wpa/src/ap/iapp.c @@ -37,7 +37,7 @@ * - IEEE 802.11 context transfer */ -#include "includes.h" +#include "utils/includes.h" #include #include #ifdef USE_KERNEL_HEADERS @@ -46,11 +46,14 @@ #include #endif /* USE_KERNEL_HEADERS */ +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" #include "hostapd.h" +#include "ap_config.h" #include "ieee802_11.h" -#include "iapp.h" -#include "eloop.h" #include "sta_info.h" +#include "iapp.h" #define IAPP_MULTICAST "224.0.1.178" @@ -304,10 +307,7 @@ static void iapp_process_add_notify(struct iapp_data *iapp, hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP, HOSTAPD_LEVEL_DEBUG, "Removing STA due to IAPP ADD-notify"); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED); - eloop_cancel_timeout(ap_handle_timer, iapp->hapd, sta); - eloop_register_timeout(0, 0, ap_handle_timer, iapp->hapd, sta); - sta->timeout_next = STA_REMOVE; + ap_sta_disconnect(iapp->hapd, sta, NULL, 0); } @@ -533,21 +533,3 @@ void iapp_deinit(struct iapp_data *iapp) } os_free(iapp); } - -int iapp_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss) -{ - if (hapd->conf->ieee802_11f != oldbss->ieee802_11f || - os_strcmp(hapd->conf->iapp_iface, oldbss->iapp_iface) != 0) { - iapp_deinit(hapd->iapp); - hapd->iapp = NULL; - - if (hapd->conf->ieee802_11f) { - hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface); - if (hapd->iapp == NULL) - return -1; - } - } - - return 0; -} diff --git a/contrib/wpa/hostapd/iapp.h b/contrib/wpa/src/ap/iapp.h similarity index 79% rename from contrib/wpa/hostapd/iapp.h rename to contrib/wpa/src/ap/iapp.h index 86de59256043..5fc01cb70355 100644 --- a/contrib/wpa/hostapd/iapp.h +++ b/contrib/wpa/src/ap/iapp.h @@ -22,8 +22,6 @@ struct iapp_data; void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta); struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface); void iapp_deinit(struct iapp_data *iapp); -int iapp_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss); #else /* CONFIG_IAPP */ @@ -42,13 +40,6 @@ static inline void iapp_deinit(struct iapp_data *iapp) { } -static inline int -iapp_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss) -{ - return 0; -} - #endif /* CONFIG_IAPP */ #endif /* IAPP_H */ diff --git a/contrib/wpa/hostapd/ieee802_11.c b/contrib/wpa/src/ap/ieee802_11.c similarity index 68% rename from contrib/wpa/hostapd/ieee802_11.c rename to contrib/wpa/src/ap/ieee802_11.c index 70491b4fa22e..3375aa2a3cf8 100644 --- a/contrib/wpa/hostapd/ieee802_11.c +++ b/contrib/wpa/src/ap/ieee802_11.c @@ -1,7 +1,6 @@ /* * hostapd / IEEE 802.11 Management - * Copyright (c) 2002-2008, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation + * Copyright (c) 2002-2010, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,29 +12,32 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" #ifndef CONFIG_NATIVE_WINDOWS -#include - -#include "eloop.h" -#include "hostapd.h" -#include "ieee802_11.h" -#include "beacon.h" -#include "hw_features.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "crypto/crypto.h" +#include "drivers/driver.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" #include "radius/radius.h" #include "radius/radius_client.h" +#include "wps/wps.h" +#include "hostapd.h" +#include "beacon.h" #include "ieee802_11_auth.h" #include "sta_info.h" -#include "rc4.h" #include "ieee802_1x.h" -#include "wpa.h" -#include "wme.h" +#include "wpa_auth.h" +#include "wmm.h" #include "ap_list.h" #include "accounting.h" -#include "driver.h" -#include "mlme.h" +#include "ap_config.h" +#include "ap_mlme.h" +#include "ieee802_11.h" u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid) @@ -100,153 +102,6 @@ u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid) } -u8 * hostapd_eid_ht_capabilities_info(struct hostapd_data *hapd, u8 *eid) -{ -#ifdef CONFIG_IEEE80211N - struct ieee80211_ht_capability *cap; - u8 *pos = eid; - - if (!hapd->iconf->ieee80211n) - return eid; - - *pos++ = WLAN_EID_HT_CAP; - *pos++ = sizeof(*cap); - - cap = (struct ieee80211_ht_capability *) pos; - os_memset(cap, 0, sizeof(*cap)); - SET_2BIT_U8(&cap->mac_ht_params_info, - MAC_HT_PARAM_INFO_MAX_RX_AMPDU_FACTOR_OFFSET, - MAX_RX_AMPDU_FACTOR_64KB); - - cap->capabilities_info = host_to_le16(hapd->iconf->ht_capab); - - cap->supported_mcs_set[0] = 0xff; - cap->supported_mcs_set[1] = 0xff; - - pos += sizeof(*cap); - - return pos; -#else /* CONFIG_IEEE80211N */ - return eid; -#endif /* CONFIG_IEEE80211N */ -} - - -u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) -{ -#ifdef CONFIG_IEEE80211N - struct ieee80211_ht_operation *oper; - u8 *pos = eid; - - if (!hapd->iconf->ieee80211n) - return eid; - - *pos++ = WLAN_EID_HT_OPERATION; - *pos++ = sizeof(*oper); - - oper = (struct ieee80211_ht_operation *) pos; - os_memset(oper, 0, sizeof(*oper)); - - oper->control_chan = hapd->iconf->channel; - oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode); - if (hapd->iconf->secondary_channel == 1) - oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE | - HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; - if (hapd->iconf->secondary_channel == -1) - oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW | - HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; - - pos += sizeof(*oper); - - return pos; -#else /* CONFIG_IEEE80211N */ - return eid; -#endif /* CONFIG_IEEE80211N */ -} - - -#ifdef CONFIG_IEEE80211N - -/* -op_mode -Set to 0 (HT pure) under the followign conditions - - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or - - all STAs in the BSS are 20 MHz HT in 20 MHz BSS -Set to 1 (HT non-member protection) if there may be non-HT STAs - in both the primary and the secondary channel -Set to 2 if only HT STAs are associated in BSS, - however and at least one 20 MHz HT STA is associated -Set to 3 (HT mixed mode) when one or more non-HT STAs are associated - (currently non-GF HT station is considered as non-HT STA also) -*/ -int hostapd_ht_operation_update(struct hostapd_iface *iface) -{ - u16 cur_op_mode, new_op_mode; - int op_mode_changes = 0; - - if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) - return 0; - - wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X", - __func__, iface->ht_op_mode); - - if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) - && iface->num_sta_ht_no_gf) { - iface->ht_op_mode |= - HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; - op_mode_changes++; - } else if ((iface->ht_op_mode & - HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) && - iface->num_sta_ht_no_gf == 0) { - iface->ht_op_mode &= - ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; - op_mode_changes++; - } - - if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && - (iface->num_sta_no_ht || iface->olbc_ht)) { - iface->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; - op_mode_changes++; - } else if ((iface->ht_op_mode & - HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && - (iface->num_sta_no_ht == 0 && !iface->olbc_ht)) { - iface->ht_op_mode &= - ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; - op_mode_changes++; - } - - /* Note: currently we switch to the MIXED op mode if HT non-greenfield - * station is associated. Probably it's a theoretical case, since - * it looks like all known HT STAs support greenfield. - */ - new_op_mode = 0; - if (iface->num_sta_no_ht || - (iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)) - new_op_mode = OP_MODE_MIXED; - else if ((iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) - && iface->num_sta_ht_20mhz) - new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED; - else if (iface->olbc_ht) - new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS; - else - new_op_mode = OP_MODE_PURE; - - cur_op_mode = iface->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK; - if (cur_op_mode != new_op_mode) { - iface->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK; - iface->ht_op_mode |= new_op_mode; - op_mode_changes++; - } - - wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d", - __func__, iface->ht_op_mode, op_mode_changes); - - return op_mode_changes; -} - -#endif /* CONFIG_IEEE80211N */ - - u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta, int probe) { @@ -336,34 +191,9 @@ void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len) } -/** - * ieee802_11_send_deauth - Send Deauthentication frame - * @hapd: hostapd BSS data - * @addr: Address of the destination STA - * @reason: Reason code for Deauthentication - */ -void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason) -{ - struct ieee80211_mgmt mgmt; - - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "deauthenticate - reason %d", reason); - os_memset(&mgmt, 0, sizeof(mgmt)); - mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, - WLAN_FC_STYPE_DEAUTH); - os_memcpy(mgmt.da, addr, ETH_ALEN); - os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); - os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); - mgmt.u.deauth.reason_code = host_to_le16(reason); - if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth), 0) < 0) - perror("ieee802_11_send_deauth: send"); -} - - static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta, - u16 auth_transaction, u8 *challenge, int iswep) + u16 auth_transaction, const u8 *challenge, + int iswep) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, @@ -452,7 +282,7 @@ static void send_auth_reply(struct hostapd_data *hapd, " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)", MAC2STR(dst), auth_alg, auth_transaction, resp, (unsigned long) ies_len); - if (hostapd_send_mgmt_frame(hapd, reply, rlen, 0) < 0) + if (hapd->drv.send_mgmt_frame(hapd, reply, rlen) < 0) perror("send_auth_reply: send"); os_free(buf); @@ -485,15 +315,15 @@ static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid, #endif /* CONFIG_IEEE80211R */ -static void handle_auth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len) +static void handle_auth(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len) { u16 auth_alg, auth_transaction, status_code; u16 resp = WLAN_STATUS_SUCCESS; struct sta_info *sta = NULL; int res; u16 fc; - u8 *challenge = NULL; + const u8 *challenge = NULL; u32 session_timeout, acct_interim_interval; int vlan_id = 0; u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; @@ -601,8 +431,7 @@ static void handle_auth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, sta->flags &= ~WLAN_STA_PREAUTH; ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); - if (hapd->conf->radius->acct_interim_interval == 0 && - acct_interim_interval) + if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval) sta->acct_interim_interval = acct_interim_interval; if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT) ap_sta_session_timeout(hapd, sta, session_timeout); @@ -665,18 +494,388 @@ static void handle_auth(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, } +static int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta) +{ + int i, j = 32, aid; + + /* get a unique AID */ + if (sta->aid > 0) { + wpa_printf(MSG_DEBUG, " old AID %d", sta->aid); + return 0; + } + + for (i = 0; i < AID_WORDS; i++) { + if (hapd->sta_aid[i] == (u32) -1) + continue; + for (j = 0; j < 32; j++) { + if (!(hapd->sta_aid[i] & BIT(j))) + break; + } + if (j < 32) + break; + } + if (j == 32) + return -1; + aid = i * 32 + j + 1; + if (aid > 2007) + return -1; + + sta->aid = aid; + hapd->sta_aid[i] |= BIT(j); + wpa_printf(MSG_DEBUG, " new AID %d", sta->aid); + return 0; +} + + +static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ssid_ie, size_t ssid_ie_len) +{ + if (ssid_ie == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + if (ssid_ie_len != hapd->conf->ssid.ssid_len || + os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0) { + char ssid_txt[33]; + ieee802_11_print_ssid(ssid_txt, ssid_ie, ssid_ie_len); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Station tried to associate with unknown SSID " + "'%s'", ssid_txt); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} + + +static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *wmm_ie, size_t wmm_ie_len) +{ + sta->flags &= ~WLAN_STA_WMM; + if (wmm_ie && hapd->conf->wmm_enabled) { + if (hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_WPA, + HOSTAPD_LEVEL_DEBUG, + "invalid WMM element in association " + "request"); + else + sta->flags |= WLAN_STA_WMM; + } + return WLAN_STATUS_SUCCESS; +} + + +static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta, + struct ieee802_11_elems *elems) +{ + if (!elems->supp_rates) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "No supported rates element in AssocReq"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + if (elems->supp_rates_len > sizeof(sta->supported_rates)) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Invalid supported rates element length %d", + elems->supp_rates_len); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + os_memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); + os_memcpy(sta->supported_rates, elems->supp_rates, + elems->supp_rates_len); + sta->supported_rates_len = elems->supp_rates_len; + + if (elems->ext_supp_rates) { + if (elems->supp_rates_len + elems->ext_supp_rates_len > + sizeof(sta->supported_rates)) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Invalid supported rates element length" + " %d+%d", elems->supp_rates_len, + elems->ext_supp_rates_len); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + os_memcpy(sta->supported_rates + elems->supp_rates_len, + elems->ext_supp_rates, elems->ext_supp_rates_len); + sta->supported_rates_len += elems->ext_supp_rates_len; + } + + return WLAN_STATUS_SUCCESS; +} + + +static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ies, size_t ies_len, int reassoc) +{ + struct ieee802_11_elems elems; + u16 resp; + const u8 *wpa_ie; + size_t wpa_ie_len; + + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "Station sent an invalid " + "association request"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + resp = check_ssid(hapd, sta, elems.ssid, elems.ssid_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + resp = check_wmm(hapd, sta, elems.wmm, elems.wmm_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + resp = copy_supp_rates(hapd, sta, &elems); + if (resp != WLAN_STATUS_SUCCESS) + return resp; +#ifdef CONFIG_IEEE80211N + resp = copy_sta_ht_capab(sta, elems.ht_capabilities, + elems.ht_capabilities_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; +#endif /* CONFIG_IEEE80211N */ + + if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) { + wpa_ie = elems.rsn_ie; + wpa_ie_len = elems.rsn_ie_len; + } else if ((hapd->conf->wpa & WPA_PROTO_WPA) && + elems.wpa_ie) { + wpa_ie = elems.wpa_ie; + wpa_ie_len = elems.wpa_ie_len; + } else { + wpa_ie = NULL; + wpa_ie_len = 0; + } + +#ifdef CONFIG_WPS + sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); + if (hapd->conf->wps_state && elems.wps_ie) { + wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association " + "Request - assume WPS is used"); + sta->flags |= WLAN_STA_WPS; + wpabuf_free(sta->wps_ie); + sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, + WPS_IE_VENDOR_TYPE); + wpa_ie = NULL; + wpa_ie_len = 0; + } else if (hapd->conf->wps_state && wpa_ie == NULL) { + wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in " + "(Re)Association Request - possible WPS use"); + sta->flags |= WLAN_STA_MAYBE_WPS; + } else +#endif /* CONFIG_WPS */ + if (hapd->conf->wpa && wpa_ie == NULL) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "No WPA/RSN IE in association request"); + return WLAN_STATUS_INVALID_IE; + } + + if (hapd->conf->wpa && wpa_ie) { + int res; + wpa_ie -= 2; + wpa_ie_len += 2; + if (sta->wpa_sm == NULL) + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, + sta->addr); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_WARNING, "Failed to initialize WPA " + "state machine"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, + wpa_ie, wpa_ie_len, + elems.mdie, elems.mdie_len); + if (res == WPA_INVALID_GROUP) + resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; + else if (res == WPA_INVALID_PAIRWISE) + resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; + else if (res == WPA_INVALID_AKMP) + resp = WLAN_STATUS_AKMP_NOT_VALID; + else if (res == WPA_ALLOC_FAIL) + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; +#ifdef CONFIG_IEEE80211W + else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) + resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) + resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; +#endif /* CONFIG_IEEE80211W */ + else if (res == WPA_INVALID_MDIE) + resp = WLAN_STATUS_INVALID_MDIE; + else if (res != WPA_IE_OK) + resp = WLAN_STATUS_INVALID_IE; + if (resp != WLAN_STATUS_SUCCESS) + return resp; +#ifdef CONFIG_IEEE80211W + if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && + sta->sa_query_count > 0) + ap_check_sa_query_timeout(hapd, sta); + if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && + (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) { + /* + * STA has already been associated with MFP and SA + * Query timeout has not been reached. Reject the + * association attempt temporarily and start SA Query, + * if one is not pending. + */ + + if (sta->sa_query_count == 0) + ap_sta_start_sa_query(hapd, sta); + + return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; + } + + if (wpa_auth_uses_mfp(sta->wpa_sm)) + sta->flags |= WLAN_STA_MFP; + else + sta->flags &= ~WLAN_STA_MFP; +#endif /* CONFIG_IEEE80211W */ + +#ifdef CONFIG_IEEE80211R + if (sta->auth_alg == WLAN_AUTH_FT) { + if (!reassoc) { + wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried " + "to use association (not " + "re-association) with FT auth_alg", + MAC2STR(sta->addr)); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + resp = wpa_ft_validate_reassoc(sta->wpa_sm, ies, + ies_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + } +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_IEEE80211N + if ((sta->flags & WLAN_STA_HT) && + wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Station tried to use TKIP with HT " + "association"); + return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; + } +#endif /* CONFIG_IEEE80211N */ + } else + wpa_auth_sta_no_wpa(sta->wpa_sm); + + return WLAN_STATUS_SUCCESS; +} + + +static void send_deauth(struct hostapd_data *hapd, const u8 *addr, + u16 reason_code) +{ + int send_len; + struct ieee80211_mgmt reply; + + os_memset(&reply, 0, sizeof(reply)); + reply.frame_control = + IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH); + os_memcpy(reply.da, addr, ETH_ALEN); + os_memcpy(reply.sa, hapd->own_addr, ETH_ALEN); + os_memcpy(reply.bssid, hapd->own_addr, ETH_ALEN); + + send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth); + reply.u.deauth.reason_code = host_to_le16(reason_code); + + if (hapd->drv.send_mgmt_frame(hapd, &reply, send_len) < 0) + wpa_printf(MSG_INFO, "Failed to send deauth: %s", + strerror(errno)); +} + + +static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, + u16 status_code, int reassoc, const u8 *ies, + size_t ies_len) +{ + int send_len; + u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; + struct ieee80211_mgmt *reply; + u8 *p; + + os_memset(buf, 0, sizeof(buf)); + reply = (struct ieee80211_mgmt *) buf; + reply->frame_control = + IEEE80211_FC(WLAN_FC_TYPE_MGMT, + (reassoc ? WLAN_FC_STYPE_REASSOC_RESP : + WLAN_FC_STYPE_ASSOC_RESP)); + os_memcpy(reply->da, sta->addr, ETH_ALEN); + os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(reply->bssid, hapd->own_addr, ETH_ALEN); + + send_len = IEEE80211_HDRLEN; + send_len += sizeof(reply->u.assoc_resp); + reply->u.assoc_resp.capab_info = + host_to_le16(hostapd_own_capab_info(hapd, sta, 0)); + reply->u.assoc_resp.status_code = host_to_le16(status_code); + reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) + | BIT(14) | BIT(15)); + /* Supported rates */ + p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable); + /* Extended supported rates */ + p = hostapd_eid_ext_supp_rates(hapd, p); + +#ifdef CONFIG_IEEE80211R + if (status_code == WLAN_STATUS_SUCCESS) { + /* IEEE 802.11r: Mobility Domain Information, Fast BSS + * Transition Information, RSN, [RIC Response] */ + p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p, + buf + sizeof(buf) - p, + sta->auth_alg, ies, ies_len); + } +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_IEEE80211W + if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) + p = hostapd_eid_assoc_comeback_time(hapd, sta, p); +#endif /* CONFIG_IEEE80211W */ + +#ifdef CONFIG_IEEE80211N + p = hostapd_eid_ht_capabilities(hapd, p); + p = hostapd_eid_ht_operation(hapd, p); +#endif /* CONFIG_IEEE80211N */ + + if (sta->flags & WLAN_STA_WMM) + p = hostapd_eid_wmm(hapd, p); + +#ifdef CONFIG_WPS + if (sta->flags & WLAN_STA_WPS) { + struct wpabuf *wps = wps_build_assoc_resp_ie(); + if (wps) { + os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps)); + p += wpabuf_len(wps); + wpabuf_free(wps); + } + } +#endif /* CONFIG_WPS */ + + send_len += p - reply->u.assoc_resp.variable; + + if (hapd->drv.send_mgmt_frame(hapd, reply, send_len) < 0) + wpa_printf(MSG_INFO, "Failed to send assoc resp: %s", + strerror(errno)); +} + + static void handle_assoc(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len, int reassoc) + const struct ieee80211_mgmt *mgmt, size_t len, + int reassoc) { u16 capab_info, listen_interval; u16 resp = WLAN_STATUS_SUCCESS; - u8 *pos, *wpa_ie; - size_t wpa_ie_len; - int send_deauth = 0, send_len, left, i; + const u8 *pos; + int left, i; struct sta_info *sta; - struct ieee802_11_elems elems; - u8 buf[sizeof(struct ieee80211_mgmt) + 512]; - struct ieee80211_mgmt *reply; if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) : sizeof(mgmt->u.assoc_req))) { @@ -717,15 +916,15 @@ static void handle_assoc(struct hostapd_data *hapd, } else #endif /* CONFIG_IEEE80211R */ if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) { - printf("STA " MACSTR " trying to associate before " - "authentication\n", MAC2STR(mgmt->sa)); - if (sta) { - printf(" sta: addr=" MACSTR " aid=%d flags=0x%04x\n", - MAC2STR(sta->addr), sta->aid, sta->flags); - } - send_deauth = 1; - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "Station tried to " + "associate before authentication " + "(aid=%d flags=0x%x)", + sta ? sta->aid : -1, + sta ? sta->flags : 0); + send_deauth(hapd, mgmt->sa, + WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA); + return; } if (hapd->tkip_countermeasures) { @@ -742,225 +941,21 @@ static void handle_assoc(struct hostapd_data *hapd, goto fail; } - sta->capability = capab_info; - sta->listen_interval = listen_interval; - /* followed by SSID and Supported rates; and HT capabilities if 802.11n * is used */ - if (ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed || - !elems.ssid) { - printf("STA " MACSTR " sent invalid association request\n", - MAC2STR(sta->addr)); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + resp = check_assoc_ies(hapd, sta, pos, left, reassoc); + if (resp != WLAN_STATUS_SUCCESS) goto fail; - } - if (elems.ssid_len != hapd->conf->ssid.ssid_len || - os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) != 0) - { - char ssid_txt[33]; - ieee802_11_print_ssid(ssid_txt, elems.ssid, elems.ssid_len); - printf("Station " MACSTR " tried to associate with " - "unknown SSID '%s'\n", MAC2STR(sta->addr), ssid_txt); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - sta->flags &= ~WLAN_STA_WMM; - if (elems.wmm && hapd->conf->wmm_enabled) { - if (hostapd_eid_wmm_valid(hapd, elems.wmm, elems.wmm_len)) - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_WPA, - HOSTAPD_LEVEL_DEBUG, - "invalid WMM element in association " - "request"); - else - sta->flags |= WLAN_STA_WMM; - } - - if (!elems.supp_rates) { + if (hostapd_get_aid(hapd, sta) < 0) { hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "No supported rates element in AssocReq"); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + HOSTAPD_LEVEL_INFO, "No room for more AIDs"); + resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; goto fail; } - if (elems.supp_rates_len > sizeof(sta->supported_rates)) { - hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Invalid supported rates element length %d", - elems.supp_rates_len); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - os_memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); - os_memcpy(sta->supported_rates, elems.supp_rates, - elems.supp_rates_len); - sta->supported_rates_len = elems.supp_rates_len; - - if (elems.ext_supp_rates) { - if (elems.supp_rates_len + elems.ext_supp_rates_len > - sizeof(sta->supported_rates)) { - hostapd_logger(hapd, mgmt->sa, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_DEBUG, - "Invalid supported rates element length" - " %d+%d", elems.supp_rates_len, - elems.ext_supp_rates_len); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - os_memcpy(sta->supported_rates + elems.supp_rates_len, - elems.ext_supp_rates, elems.ext_supp_rates_len); - sta->supported_rates_len += elems.ext_supp_rates_len; - } - -#ifdef CONFIG_IEEE80211N - /* save HT capabilities in the sta object */ - os_memset(&sta->ht_capabilities, 0, sizeof(sta->ht_capabilities)); - if (elems.ht_capabilities && - elems.ht_capabilities_len >= - sizeof(struct ieee80211_ht_capability)) { - sta->flags |= WLAN_STA_HT; - sta->ht_capabilities.id = WLAN_EID_HT_CAP; - sta->ht_capabilities.length = - sizeof(struct ieee80211_ht_capability); - os_memcpy(&sta->ht_capabilities.data, - elems.ht_capabilities, - sizeof(struct ieee80211_ht_capability)); - } else - sta->flags &= ~WLAN_STA_HT; -#endif /* CONFIG_IEEE80211N */ - - if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) { - wpa_ie = elems.rsn_ie; - wpa_ie_len = elems.rsn_ie_len; - } else if ((hapd->conf->wpa & WPA_PROTO_WPA) && - elems.wpa_ie) { - wpa_ie = elems.wpa_ie; - wpa_ie_len = elems.wpa_ie_len; - } else { - wpa_ie = NULL; - wpa_ie_len = 0; - } -#ifdef CONFIG_WPS - sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS); - if (hapd->conf->wps_state && wpa_ie == NULL) { - if (elems.wps_ie) { - wpa_printf(MSG_DEBUG, "STA included WPS IE in " - "(Re)Association Request - assume WPS is " - "used"); - sta->flags |= WLAN_STA_WPS; - wpabuf_free(sta->wps_ie); - sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4, - elems.wps_ie_len - 4); - } else { - wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE " - "in (Re)Association Request - possible WPS " - "use"); - sta->flags |= WLAN_STA_MAYBE_WPS; - } - } else -#endif /* CONFIG_WPS */ - if (hapd->conf->wpa && wpa_ie == NULL) { - printf("STA " MACSTR ": No WPA/RSN IE in association " - "request\n", MAC2STR(sta->addr)); - resp = WLAN_STATUS_INVALID_IE; - goto fail; - } - - if (hapd->conf->wpa && wpa_ie) { - int res; - wpa_ie -= 2; - wpa_ie_len += 2; - if (sta->wpa_sm == NULL) - sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, - sta->addr); - if (sta->wpa_sm == NULL) { - printf("Failed to initialize WPA state machine\n"); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, - wpa_ie, wpa_ie_len, - elems.mdie, elems.mdie_len); - if (res == WPA_INVALID_GROUP) - resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; - else if (res == WPA_INVALID_PAIRWISE) - resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - else if (res == WPA_INVALID_AKMP) - resp = WLAN_STATUS_AKMP_NOT_VALID; - else if (res == WPA_ALLOC_FAIL) - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; -#ifdef CONFIG_IEEE80211W - else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) - resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; - else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) - resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; -#endif /* CONFIG_IEEE80211W */ - else if (res == WPA_INVALID_MDIE) - resp = WLAN_STATUS_INVALID_MDIE; - else if (res != WPA_IE_OK) - resp = WLAN_STATUS_INVALID_IE; - if (resp != WLAN_STATUS_SUCCESS) - goto fail; -#ifdef CONFIG_IEEE80211W - if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && - sta->sa_query_count > 0) - ap_check_sa_query_timeout(hapd, sta); - if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && - (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) { - /* - * STA has already been associated with MFP and SA - * Query timeout has not been reached. Reject the - * association attempt temporarily and start SA Query, - * if one is not pending. - */ - - if (sta->sa_query_count == 0) - ap_sta_start_sa_query(hapd, sta); - - resp = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; - goto fail; - } - - if (wpa_auth_uses_mfp(sta->wpa_sm)) - sta->flags |= WLAN_STA_MFP; - else - sta->flags &= ~WLAN_STA_MFP; -#endif /* CONFIG_IEEE80211W */ - -#ifdef CONFIG_IEEE80211R - if (sta->auth_alg == WLAN_AUTH_FT) { - if (!reassoc) { - wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried " - "to use association (not " - "re-association) with FT auth_alg", - MAC2STR(sta->addr)); - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - resp = wpa_ft_validate_reassoc(sta->wpa_sm, pos, left); - if (resp != WLAN_STATUS_SUCCESS) - goto fail; - } -#endif /* CONFIG_IEEE80211R */ -#ifdef CONFIG_IEEE80211N - if ((sta->flags & WLAN_STA_HT) && - wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) { - wpa_printf(MSG_DEBUG, "HT: " MACSTR " tried to " - "use TKIP with HT association", - MAC2STR(sta->addr)); - resp = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; - goto fail; - } -#endif /* CONFIG_IEEE80211N */ - } else - wpa_auth_sta_no_wpa(sta->wpa_sm); + sta->capability = capab_info; + sta->listen_interval = listen_interval; if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) sta->flags |= WLAN_STA_NONERP; @@ -1002,66 +997,9 @@ static void handle_assoc(struct hostapd_data *hapd, } #ifdef CONFIG_IEEE80211N - if (sta->flags & WLAN_STA_HT) { - u16 ht_capab = le_to_host16( - sta->ht_capabilities.data.capabilities_info); - wpa_printf(MSG_DEBUG, "HT: STA " MACSTR " HT Capabilities " - "Info: 0x%04x", MAC2STR(sta->addr), ht_capab); - if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) { - if (!sta->no_ht_gf_set) { - sta->no_ht_gf_set = 1; - hapd->iface->num_sta_ht_no_gf++; - } - wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no " - "greenfield, num of non-gf stations %d", - __func__, MAC2STR(sta->addr), - hapd->iface->num_sta_ht_no_gf); - } - if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) { - if (!sta->ht_20mhz_set) { - sta->ht_20mhz_set = 1; - hapd->iface->num_sta_ht_20mhz++; - } - wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - 20 MHz HT, " - "num of 20MHz HT STAs %d", - __func__, MAC2STR(sta->addr), - hapd->iface->num_sta_ht_20mhz); - } - } else { - if (!sta->no_ht_set) { - sta->no_ht_set = 1; - hapd->iface->num_sta_no_ht++; - } - if (hapd->iconf->ieee80211n) { - wpa_printf(MSG_DEBUG, "%s STA " MACSTR - " - no HT, num of non-HT stations %d", - __func__, MAC2STR(sta->addr), - hapd->iface->num_sta_no_ht); - } - } - - if (hostapd_ht_operation_update(hapd->iface) > 0) - ieee802_11_set_beacons(hapd->iface); + update_ht_state(hapd, sta); #endif /* CONFIG_IEEE80211N */ - /* get a unique AID */ - if (sta->aid > 0) { - wpa_printf(MSG_DEBUG, " old AID %d", sta->aid); - } else { - for (sta->aid = 1; sta->aid <= MAX_AID_TABLE_SIZE; sta->aid++) - if (hapd->sta_aid[sta->aid - 1] == NULL) - break; - if (sta->aid > MAX_AID_TABLE_SIZE) { - sta->aid = 0; - resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - wpa_printf(MSG_ERROR, " no room for more AIDs"); - goto fail; - } else { - hapd->sta_aid[sta->aid - 1] = sta; - wpa_printf(MSG_DEBUG, " new AID %d", sta->aid); - } - } - hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "association OK (aid %d)", sta->aid); @@ -1097,64 +1035,12 @@ static void handle_assoc(struct hostapd_data *hapd, sta->timeout_next = STA_NULLFUNC; fail: - os_memset(buf, 0, sizeof(buf)); - reply = (struct ieee80211_mgmt *) buf; - reply->frame_control = - IEEE80211_FC(WLAN_FC_TYPE_MGMT, - (send_deauth ? WLAN_FC_STYPE_DEAUTH : - (reassoc ? WLAN_FC_STYPE_REASSOC_RESP : - WLAN_FC_STYPE_ASSOC_RESP))); - os_memcpy(reply->da, mgmt->sa, ETH_ALEN); - os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(reply->bssid, mgmt->bssid, ETH_ALEN); - - send_len = IEEE80211_HDRLEN; - if (send_deauth) { - send_len += sizeof(reply->u.deauth); - reply->u.deauth.reason_code = host_to_le16(resp); - } else { - u8 *p; - send_len += sizeof(reply->u.assoc_resp); - reply->u.assoc_resp.capab_info = - host_to_le16(hostapd_own_capab_info(hapd, sta, 0)); - reply->u.assoc_resp.status_code = host_to_le16(resp); - reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) - | BIT(14) | BIT(15)); - /* Supported rates */ - p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable); - /* Extended supported rates */ - p = hostapd_eid_ext_supp_rates(hapd, p); - if (sta->flags & WLAN_STA_WMM) - p = hostapd_eid_wmm(hapd, p); - - p = hostapd_eid_ht_capabilities_info(hapd, p); - p = hostapd_eid_ht_operation(hapd, p); - -#ifdef CONFIG_IEEE80211R - if (resp == WLAN_STATUS_SUCCESS) { - /* IEEE 802.11r: Mobility Domain Information, Fast BSS - * Transition Information, RSN */ - p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p, - buf + sizeof(buf) - p, - sta->auth_alg); - } -#endif /* CONFIG_IEEE80211R */ - -#ifdef CONFIG_IEEE80211W - if (resp == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) - p = hostapd_eid_assoc_comeback_time(hapd, sta, p); -#endif /* CONFIG_IEEE80211W */ - - send_len += p - reply->u.assoc_resp.variable; - } - - if (hostapd_send_mgmt_frame(hapd, reply, send_len, 0) < 0) - perror("handle_assoc: send"); + send_assoc_resp(hapd, sta, resp, reassoc, pos, left); } static void handle_disassoc(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len) + const struct ieee80211_mgmt *mgmt, size_t len) { struct sta_info *sta; @@ -1176,6 +1062,8 @@ static void handle_disassoc(struct hostapd_data *hapd, } sta->flags &= ~WLAN_STA_ASSOC; + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR, + MAC2STR(sta->addr)); wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated"); @@ -1185,7 +1073,7 @@ static void handle_disassoc(struct hostapd_data *hapd, * authenticated. */ accounting_sta_stop(hapd, sta); ieee802_1x_free_station(sta); - hostapd_sta_remove(hapd, sta->addr); + hapd->drv.sta_remove(hapd, sta->addr); if (sta->timeout_next == STA_NULLFUNC || sta->timeout_next == STA_DISASSOC) { @@ -1201,7 +1089,7 @@ static void handle_disassoc(struct hostapd_data *hapd, static void handle_deauth(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len) + const struct ieee80211_mgmt *mgmt, size_t len) { struct sta_info *sta; @@ -1224,6 +1112,8 @@ static void handle_deauth(struct hostapd_data *hapd, } sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED MACSTR, + MAC2STR(sta->addr)); wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "deauthenticated"); @@ -1236,7 +1126,7 @@ static void handle_deauth(struct hostapd_data *hapd, static void handle_beacon(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len, + const struct ieee80211_mgmt *mgmt, size_t len, struct hostapd_frame_info *fi) { struct ieee802_11_elems elems; @@ -1281,16 +1171,57 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id, WLAN_SA_QUERY_TR_ID_LEN); end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; - if (hostapd_send_mgmt_frame(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0) + if (hapd->drv.send_mgmt_frame(hapd, &mgmt, end - (u8 *) &mgmt) < 0) perror("ieee802_11_send_sa_query_req: send"); } -static void hostapd_sa_query_action(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len) +static void hostapd_sa_query_request(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt) { struct sta_info *sta; + struct ieee80211_mgmt resp; u8 *end; + + wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from " + MACSTR, MAC2STR(mgmt->sa)); + wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", + mgmt->u.action.u.sa_query_resp.trans_id, + WLAN_SA_QUERY_TR_ID_LEN); + + sta = ap_get_sta(hapd, mgmt->sa); + if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) { + wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request " + "from unassociated STA " MACSTR, MAC2STR(mgmt->sa)); + return; + } + + wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to " + MACSTR, MAC2STR(mgmt->sa)); + + os_memset(&resp, 0, sizeof(resp)); + resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(resp.da, mgmt->sa, ETH_ALEN); + os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN); + os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN); + resp.u.action.category = WLAN_ACTION_SA_QUERY; + resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE; + os_memcpy(resp.u.action.u.sa_query_req.trans_id, + mgmt->u.action.u.sa_query_req.trans_id, + WLAN_SA_QUERY_TR_ID_LEN); + end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; + if (hapd->drv.send_mgmt_frame(hapd, &resp, end - (u8 *) &resp) < 0) + perror("hostapd_sa_query_request: send"); +} + + +static void hostapd_sa_query_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len) +{ + struct sta_info *sta; + const u8 *end; int i; end = mgmt->u.action.u.sa_query_resp.trans_id + @@ -1301,6 +1232,11 @@ static void hostapd_sa_query_action(struct hostapd_data *hapd, return; } + if (mgmt->u.action.u.sa_query_resp.action == WLAN_SA_QUERY_REQUEST) { + hostapd_sa_query_request(hapd, mgmt); + return; + } + if (mgmt->u.action.u.sa_query_resp.action != WLAN_SA_QUERY_RESPONSE) { wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query " "Action %d", mgmt->u.action.u.sa_query_resp.action); @@ -1352,7 +1288,7 @@ static int robust_action_frame(u8 category) static void handle_action(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, size_t len) + const struct ieee80211_mgmt *mgmt, size_t len) { struct sta_info *sta; @@ -1403,6 +1339,14 @@ static void handle_action(struct hostapd_data *hapd, hostapd_sa_query_action(hapd, mgmt, len); return; #endif /* CONFIG_IEEE80211W */ + case WLAN_ACTION_PUBLIC: + if (hapd->public_action_cb) { + hapd->public_action_cb(hapd->public_action_cb_ctx, + (u8 *) mgmt, len, + hapd->iface->freq); + return; + } + break; } hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, @@ -1412,6 +1356,8 @@ static void handle_action(struct hostapd_data *hapd, mgmt->u.action.category); if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) && !(mgmt->sa[0] & 0x01)) { + struct ieee80211_mgmt *resp; + /* * IEEE 802.11-REVma/D9.0 - 7.3.1.11 * Return the Action frame to the source without change @@ -1419,12 +1365,17 @@ static void handle_action(struct hostapd_data *hapd, */ wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action " "frame back to sender"); - os_memcpy(mgmt->da, mgmt->sa, ETH_ALEN); - os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); - os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); - mgmt->u.action.category |= 0x80; + resp = os_malloc(len); + if (resp == NULL) + return; + os_memcpy(resp, mgmt, len); + os_memcpy(resp->da, resp->sa, ETH_ALEN); + os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); + resp->u.action.category |= 0x80; - hostapd_send_mgmt_frame(hapd, mgmt, len, 0); + hapd->drv.send_mgmt_frame(hapd, resp, len); + os_free(resp); } } @@ -1435,7 +1386,6 @@ static void handle_action(struct hostapd_data *hapd, * sent to) * @buf: management frame data (starting from IEEE 802.11 header) * @len: length of frame data in octets - * @stype: management frame subtype from frame control field * @fi: meta data about received frame (signal level, etc.) * * Process all incoming IEEE 802.11 management frames. This will be called for @@ -1443,20 +1393,22 @@ static void handle_action(struct hostapd_data *hapd, * addition, it can be called to re-inserted pending frames (e.g., when using * external RADIUS server as an MAC ACL). */ -void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, u16 stype, +void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, struct hostapd_frame_info *fi) { - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf; + struct ieee80211_mgmt *mgmt; int broadcast; + u16 fc, stype; + + mgmt = (struct ieee80211_mgmt *) buf; + fc = le_to_host16(mgmt->frame_control); + stype = WLAN_FC_GET_STYPE(fc); if (stype == WLAN_FC_STYPE_BEACON) { handle_beacon(hapd, mgmt, len, fi); return; } - if (fi && fi->passive_scan) - return; - broadcast = mgmt->bssid[0] == 0xff && mgmt->bssid[1] == 0xff && mgmt->bssid[2] == 0xff && mgmt->bssid[3] == 0xff && mgmt->bssid[4] == 0xff && mgmt->bssid[5] == 0xff; @@ -1517,7 +1469,7 @@ void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, u16 stype, static void handle_auth_cb(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, + const struct ieee80211_mgmt *mgmt, size_t len, int ok) { u16 auth_alg, auth_transaction, status_code; @@ -1557,38 +1509,14 @@ static void handle_auth_cb(struct hostapd_data *hapd, } -#ifdef CONFIG_IEEE80211N -static void -hostapd_get_ht_capab(struct hostapd_data *hapd, - struct ht_cap_ie *ht_cap_ie, - struct ht_cap_ie *neg_ht_cap_ie) -{ - u16 cap; - - os_memcpy(neg_ht_cap_ie, ht_cap_ie, sizeof(struct ht_cap_ie)); - cap = le_to_host16(neg_ht_cap_ie->data.capabilities_info); - cap &= hapd->iconf->ht_capab; - cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED); - - /* FIXME: Rx STBC needs to be handled specially */ - cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_RX_STBC_MASK); - neg_ht_cap_ie->data.capabilities_info = host_to_le16(cap); -} -#endif /* CONFIG_IEEE80211N */ - - static void handle_assoc_cb(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, + const struct ieee80211_mgmt *mgmt, size_t len, int reassoc, int ok) { u16 status; struct sta_info *sta; int new_assoc = 1; -#ifdef CONFIG_IEEE80211N - struct ht_cap_ie ht_cap; -#endif /* CONFIG_IEEE80211N */ - struct ht_cap_ie *ht_cap_ptr = NULL; - int set_flags, flags_and, flags_or; + struct ieee80211_ht_capabilities ht_cap; if (!ok) { hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211, @@ -1631,19 +1559,22 @@ static void handle_assoc_cb(struct hostapd_data *hapd, if (sta->flags & WLAN_STA_ASSOC) new_assoc = 0; sta->flags |= WLAN_STA_ASSOC; + if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa) || + sta->auth_alg == WLAN_AUTH_FT) { + /* + * Open, static WEP, or FT protocol; no separate authorization + * step. + */ + sta->flags |= WLAN_STA_AUTHORIZED; + wpa_msg(hapd->msg_ctx, MSG_INFO, + AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr)); + } if (reassoc) mlme_reassociate_indication(hapd, sta); else mlme_associate_indication(hapd, sta); -#ifdef CONFIG_IEEE80211N - if (sta->flags & WLAN_STA_HT) { - ht_cap_ptr = &ht_cap; - hostapd_get_ht_capab(hapd, &sta->ht_capabilities, ht_cap_ptr); - } -#endif /* CONFIG_IEEE80211N */ - #ifdef CONFIG_IEEE80211W sta->sa_query_timed_out = 0; #endif /* CONFIG_IEEE80211W */ @@ -1653,13 +1584,17 @@ static void handle_assoc_cb(struct hostapd_data *hapd, * cleared and configuration gets updated in case of reassociation back * to the same AP. */ - hostapd_sta_remove(hapd, sta->addr); + hapd->drv.sta_remove(hapd, sta->addr); - if (hostapd_sta_add(hapd->conf->iface, hapd, sta->addr, sta->aid, - sta->capability, sta->supported_rates, - sta->supported_rates_len, 0, sta->listen_interval, - ht_cap_ptr)) - { +#ifdef CONFIG_IEEE80211N + if (sta->flags & WLAN_STA_HT) + hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap); +#endif /* CONFIG_IEEE80211N */ + + if (hapd->drv.sta_add(hapd, sta->addr, sta->aid, sta->capability, + sta->supported_rates, sta->supported_rates_len, + sta->listen_interval, + sta->flags & WLAN_STA_HT ? &ht_cap : NULL)) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE, "Could not add STA to kernel driver"); @@ -1671,26 +1606,21 @@ static void handle_assoc_cb(struct hostapd_data *hapd, * so bind it to the selected VLAN interface now, since the * interface selection is not going to change anymore. */ - ap_sta_bind_vlan(hapd, sta, 0); + if (ap_sta_bind_vlan(hapd, sta, 0) < 0) + goto fail; } else if (sta->vlan_id) { /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */ - ap_sta_bind_vlan(hapd, sta, 0); + if (ap_sta_bind_vlan(hapd, sta, 0) < 0) + goto fail; } - set_flags = WLAN_STA_SHORT_PREAMBLE | WLAN_STA_WMM | WLAN_STA_MFP; - if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && - sta->flags & WLAN_STA_AUTHORIZED) - set_flags |= WLAN_STA_AUTHORIZED; - flags_or = sta->flags & set_flags; - flags_and = sta->flags | ~set_flags; - hostapd_sta_set_flags(hapd, sta->addr, sta->flags, - flags_or, flags_and); + hapd->drv.set_sta_flags(hapd, sta); if (sta->auth_alg == WLAN_AUTH_FT) wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT); else wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); - hostapd_new_assoc_sta(hapd, sta, !new_assoc); + hapd->new_assoc_sta_cb(hapd, sta, !new_assoc); ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); @@ -1712,10 +1642,11 @@ static void handle_assoc_cb(struct hostapd_data *hapd, * @stype: management frame subtype from frame control field * @ok: Whether the frame was ACK'ed */ -void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len, +void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len, u16 stype, int ok) { - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) buf; + const struct ieee80211_mgmt *mgmt; + mgmt = (const struct ieee80211_mgmt *) buf; switch (stype) { case WLAN_FC_STYPE_AUTH: @@ -1746,76 +1677,6 @@ void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len, } -static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx, - void *timeout_ctx) -{ - struct hostapd_data *hapd = eloop_ctx; - hapd->tkip_countermeasures = 0; - hostapd_set_countermeasures(hapd, 0); - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended"); -} - - -static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd) -{ - struct sta_info *sta; - - hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated"); - - wpa_auth_countermeasures_start(hapd->wpa_auth); - hapd->tkip_countermeasures = 1; - hostapd_set_countermeasures(hapd, 1); - wpa_gtk_rekey(hapd->wpa_auth); - eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL); - eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop, - hapd, NULL); - for (sta = hapd->sta_list; sta != NULL; sta = sta->next) { - hostapd_sta_deauth(hapd, sta->addr, - WLAN_REASON_MICHAEL_MIC_FAILURE); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | - WLAN_STA_AUTHORIZED); - hostapd_sta_remove(hapd, sta->addr); - } -} - - -void ieee80211_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, - int local) -{ - time_t now; - - if (addr && local) { - struct sta_info *sta = ap_get_sta(hapd, addr); - if (sta != NULL) { - wpa_auth_sta_local_mic_failure_report(sta->wpa_sm); - hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_INFO, - "Michael MIC failure detected in " - "received frame"); - mlme_michaelmicfailure_indication(hapd, addr); - } else { - wpa_printf(MSG_DEBUG, - "MLME-MICHAELMICFAILURE.indication " - "for not associated STA (" MACSTR - ") ignored", MAC2STR(addr)); - return; - } - } - - time(&now); - if (now > hapd->michael_mic_failure + 60) { - hapd->michael_mic_failures = 1; - } else { - hapd->michael_mic_failures++; - if (hapd->michael_mic_failures > 1) - ieee80211_tkip_countermeasures_start(hapd); - } - hapd->michael_mic_failure = now; -} - - int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen) { /* TODO */ @@ -1830,4 +1691,65 @@ int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, return 0; } + +void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, + const u8 *buf, size_t len, int ack) +{ + struct sta_info *sta; + struct hostapd_iface *iface = hapd->iface; + + sta = ap_get_sta(hapd, addr); + if (sta == NULL && iface->num_bss > 1) { + size_t j; + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + sta = ap_get_sta(hapd, addr); + if (sta) + break; + } + } + if (sta == NULL) + return; + if (sta->flags & WLAN_STA_PENDING_POLL) { + wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending " + "activity poll", MAC2STR(sta->addr), + ack ? "ACKed" : "did not ACK"); + if (ack) + sta->flags &= ~WLAN_STA_PENDING_POLL; + } + + ieee802_1x_tx_status(hapd, sta, buf, len, ack); +} + + +void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, + int wds) +{ + struct sta_info *sta; + + sta = ap_get_sta(hapd, src); + if (sta && (sta->flags & WLAN_STA_ASSOC)) { + if (wds && !(sta->flags & WLAN_STA_WDS)) { + wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for " + "STA " MACSTR " (aid %u)", + MAC2STR(sta->addr), sta->aid); + sta->flags |= WLAN_STA_WDS; + hapd->drv.set_wds_sta(hapd, sta->addr, sta->aid, 1); + } + return; + } + + wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA " + MACSTR, MAC2STR(src)); + if (sta && (sta->flags & WLAN_STA_AUTH)) + hapd->drv.sta_disassoc( + hapd, src, + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); + else + hapd->drv.sta_deauth( + hapd, src, + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); +} + + #endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/contrib/wpa/hostapd/ieee802_11.h b/contrib/wpa/src/ap/ieee802_11.h similarity index 50% rename from contrib/wpa/hostapd/ieee802_11.h rename to contrib/wpa/src/ap/ieee802_11.h index ca8ef93c090e..cfc069c8094f 100644 --- a/contrib/wpa/hostapd/ieee802_11.h +++ b/contrib/wpa/src/ap/ieee802_11.h @@ -1,7 +1,6 @@ /* * hostapd / IEEE 802.11 Management - * Copyright (c) 2002-2006, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation + * Copyright (c) 2002-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,41 +15,53 @@ #ifndef IEEE802_11_H #define IEEE802_11_H -#include "ieee802_11_defs.h" -#include "ieee802_11_common.h" - -struct hostapd_frame_info { - u32 phytype; - u32 channel; - u32 datarate; - u32 ssi_signal; - - unsigned int passive_scan:1; -}; - struct hostapd_iface; struct hostapd_data; struct sta_info; +struct hostapd_frame_info; +struct ieee80211_ht_capabilities; -void ieee802_11_send_deauth(struct hostapd_data *hapd, u8 *addr, u16 reason); -void ieee802_11_mgmt(struct hostapd_data *hapd, u8 *buf, size_t len, - u16 stype, struct hostapd_frame_info *fi); -void ieee802_11_mgmt_cb(struct hostapd_data *hapd, u8 *buf, size_t len, +void ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, + struct hostapd_frame_info *fi); +void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len, u16 stype, int ok); void ieee802_11_print_ssid(char *buf, const u8 *ssid, u8 len); -void ieee80211_michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, - int local); +#ifdef NEED_AP_MLME int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen); int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, char *buf, size_t buflen); +#else /* NEED_AP_MLME */ +static inline int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, + size_t buflen) +{ + return 0; +} + +static inline int ieee802_11_get_mib_sta(struct hostapd_data *hapd, + struct sta_info *sta, + char *buf, size_t buflen) +{ + return 0; +} +#endif /* NEED_AP_MLME */ u16 hostapd_own_capab_info(struct hostapd_data *hapd, struct sta_info *sta, int probe); u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid); -u8 * hostapd_eid_ht_capabilities_info(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid); int hostapd_ht_operation_update(struct hostapd_iface *iface); void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, const u8 *addr, const u8 *trans_id); +void hostapd_get_ht_capab(struct hostapd_data *hapd, + struct ieee80211_ht_capabilities *ht_cap, + struct ieee80211_ht_capabilities *neg_ht_cap); +u16 copy_sta_ht_capab(struct sta_info *sta, const u8 *ht_capab, + size_t ht_capab_len); +void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta); +void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, + const u8 *buf, size_t len, int ack); +void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, + int wds); #endif /* IEEE802_11_H */ diff --git a/contrib/wpa/hostapd/ieee802_11_auth.c b/contrib/wpa/src/ap/ieee802_11_auth.c similarity index 92% rename from contrib/wpa/hostapd/ieee802_11_auth.c rename to contrib/wpa/src/ap/ieee802_11_auth.c index 9aba1fe854bd..dec56d1e1a1e 100644 --- a/contrib/wpa/hostapd/ieee802_11_auth.c +++ b/contrib/wpa/src/ap/ieee802_11_auth.c @@ -1,6 +1,6 @@ /* * hostapd / IEEE 802.11 authentication (ACL) - * Copyright (c) 2003-2007, Jouni Malinen + * Copyright (c) 2003-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -17,17 +17,16 @@ * authentication frame processing. */ -#include "includes.h" +#include "utils/includes.h" -#ifndef CONFIG_NATIVE_WINDOWS - -#include "hostapd.h" -#include "ieee802_11.h" -#include "ieee802_11_auth.h" +#include "utils/common.h" +#include "utils/eloop.h" #include "radius/radius.h" #include "radius/radius_client.h" -#include "eloop.h" -#include "driver.h" +#include "hostapd.h" +#include "ap_config.h" +#include "ieee802_11.h" +#include "ieee802_11_auth.h" #define RADIUS_ACL_TIMEOUT 30 @@ -53,6 +52,7 @@ struct hostapd_acl_query_data { }; +#ifndef CONFIG_NO_RADIUS static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache) { struct hostapd_cached_radius_acl *prev; @@ -96,6 +96,7 @@ static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr, return -1; } +#endif /* CONFIG_NO_RADIUS */ static void hostapd_acl_query_free(struct hostapd_acl_query_data *query) @@ -107,6 +108,7 @@ static void hostapd_acl_query_free(struct hostapd_acl_query_data *query) } +#ifndef CONFIG_NO_RADIUS static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, struct hostapd_acl_query_data *query) { @@ -193,9 +195,9 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, fail: radius_msg_free(msg); - os_free(msg); return -1; } +#endif /* CONFIG_NO_RADIUS */ /** @@ -234,6 +236,9 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, return HOSTAPD_ACL_REJECT; if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) { +#ifdef CONFIG_NO_RADIUS + return HOSTAPD_ACL_REJECT; +#else /* CONFIG_NO_RADIUS */ struct hostapd_acl_query_data *query; /* Check whether ACL cache has an entry for this station */ @@ -289,12 +294,14 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, /* Queued data will be processed in hostapd_acl_recv_radius() * when RADIUS server replies to the sent Access-Request. */ return HOSTAPD_ACL_PENDING; +#endif /* CONFIG_NO_RADIUS */ } return HOSTAPD_ACL_REJECT; } +#ifndef CONFIG_NO_RADIUS static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now) { struct hostapd_cached_radius_acl *prev, *entry, *tmp; @@ -311,7 +318,7 @@ static void hostapd_acl_expire_cache(struct hostapd_data *hapd, time_t now) else hapd->acl_cache = entry->next; #ifdef CONFIG_DRIVER_RADIUS_ACL - hostapd_set_radius_acl_expire(hapd, entry->addr); + hapd->drv.set_radius_acl_expire(hapd, entry->addr); #endif /* CONFIG_DRIVER_RADIUS_ACL */ tmp = entry; entry = entry->next; @@ -389,11 +396,12 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, struct hostapd_data *hapd = data; struct hostapd_acl_query_data *query, *prev; struct hostapd_cached_radius_acl *cache; + struct radius_hdr *hdr = radius_msg_get_hdr(msg); query = hapd->acl_queries; prev = NULL; while (query) { - if (query->radius_id == msg->hdr->identifier) + if (query->radius_id == hdr->identifier) break; prev = query; query = query->next; @@ -410,10 +418,10 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, return RADIUS_RX_INVALID_AUTHENTICATOR; } - if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT && - msg->hdr->code != RADIUS_CODE_ACCESS_REJECT) { + if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT && + hdr->code != RADIUS_CODE_ACCESS_REJECT) { wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL " - "query", msg->hdr->code); + "query", hdr->code); return RADIUS_RX_UNKNOWN; } @@ -425,7 +433,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, } time(&cache->timestamp); os_memcpy(cache->addr, query->addr, sizeof(cache->addr)); - if (msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT) { + if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) { if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, &cache->session_timeout) == 0) cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT; @@ -450,14 +458,15 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, hapd->acl_cache = cache; #ifdef CONFIG_DRIVER_RADIUS_ACL - hostapd_set_radius_acl_auth(hapd, query->addr, cache->accepted, - cache->session_timeout); + hapd->drv.set_radius_acl_auth(hapd, query->addr, cache->accepted, + cache->session_timeout); #else /* CONFIG_DRIVER_RADIUS_ACL */ +#ifdef NEED_AP_MLME /* Re-send original authentication frame for 802.11 processing */ wpa_printf(MSG_DEBUG, "Re-sending authentication frame after " "successful RADIUS ACL query"); - ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, - WLAN_FC_STYPE_AUTH, NULL); + ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL); +#endif /* NEED_AP_MLME */ #endif /* CONFIG_DRIVER_RADIUS_ACL */ done: @@ -470,6 +479,7 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, return RADIUS_RX_PROCESSED; } +#endif /* CONFIG_NO_RADIUS */ /** @@ -479,11 +489,13 @@ hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, */ int hostapd_acl_init(struct hostapd_data *hapd) { +#ifndef CONFIG_NO_RADIUS if (radius_client_register(hapd->radius, RADIUS_AUTH, hostapd_acl_recv_radius, hapd)) return -1; eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL); +#endif /* CONFIG_NO_RADIUS */ return 0; } @@ -497,9 +509,11 @@ void hostapd_acl_deinit(struct hostapd_data *hapd) { struct hostapd_acl_query_data *query, *prev; +#ifndef CONFIG_NO_RADIUS eloop_cancel_timeout(hostapd_acl_expire, hapd, NULL); hostapd_acl_cache_free(hapd->acl_cache); +#endif /* CONFIG_NO_RADIUS */ query = hapd->acl_queries; while (query) { @@ -508,16 +522,3 @@ void hostapd_acl_deinit(struct hostapd_data *hapd) hostapd_acl_query_free(prev); } } - - -int hostapd_acl_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf) -{ - if (!hapd->radius_client_reconfigured) - return 0; - - hostapd_acl_deinit(hapd); - return hostapd_acl_init(hapd); -} - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/contrib/wpa/hostapd/ieee802_11_auth.h b/contrib/wpa/src/ap/ieee802_11_auth.h similarity index 91% rename from contrib/wpa/hostapd/ieee802_11_auth.h rename to contrib/wpa/src/ap/ieee802_11_auth.h index 0eed825e29a4..b2971e5092b5 100644 --- a/contrib/wpa/hostapd/ieee802_11_auth.h +++ b/contrib/wpa/src/ap/ieee802_11_auth.h @@ -27,7 +27,5 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, u32 *acct_interim_interval, int *vlan_id); int hostapd_acl_init(struct hostapd_data *hapd); void hostapd_acl_deinit(struct hostapd_data *hapd); -int hostapd_acl_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf); #endif /* IEEE802_11_AUTH_H */ diff --git a/contrib/wpa/src/ap/ieee802_11_ht.c b/contrib/wpa/src/ap/ieee802_11_ht.c new file mode 100644 index 000000000000..7541b83816d0 --- /dev/null +++ b/contrib/wpa/src/ap/ieee802_11_ht.c @@ -0,0 +1,270 @@ +/* + * hostapd / IEEE 802.11n HT + * Copyright (c) 2002-2009, Jouni Malinen + * Copyright (c) 2007-2008, Intel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "drivers/driver.h" +#include "hostapd.h" +#include "ap_config.h" +#include "sta_info.h" +#include "beacon.h" +#include "ieee802_11.h" + + +u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid) +{ + struct ieee80211_ht_capabilities *cap; + u8 *pos = eid; + + if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode) + return eid; + + *pos++ = WLAN_EID_HT_CAP; + *pos++ = sizeof(*cap); + + cap = (struct ieee80211_ht_capabilities *) pos; + os_memset(cap, 0, sizeof(*cap)); + cap->ht_capabilities_info = host_to_le16(hapd->iconf->ht_capab); + cap->a_mpdu_params = hapd->iface->current_mode->a_mpdu_params; + os_memcpy(cap->supported_mcs_set, hapd->iface->current_mode->mcs_set, + 16); + + /* TODO: ht_extended_capabilities (now fully disabled) */ + /* TODO: tx_bf_capability_info (now fully disabled) */ + /* TODO: asel_capabilities (now fully disabled) */ + + pos += sizeof(*cap); + + return pos; +} + + +u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) +{ + struct ieee80211_ht_operation *oper; + u8 *pos = eid; + + if (!hapd->iconf->ieee80211n) + return eid; + + *pos++ = WLAN_EID_HT_OPERATION; + *pos++ = sizeof(*oper); + + oper = (struct ieee80211_ht_operation *) pos; + os_memset(oper, 0, sizeof(*oper)); + + oper->control_chan = hapd->iconf->channel; + oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode); + if (hapd->iconf->secondary_channel == 1) + oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE | + HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; + if (hapd->iconf->secondary_channel == -1) + oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW | + HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH; + + pos += sizeof(*oper); + + return pos; +} + + +/* +op_mode +Set to 0 (HT pure) under the followign conditions + - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or + - all STAs in the BSS are 20 MHz HT in 20 MHz BSS +Set to 1 (HT non-member protection) if there may be non-HT STAs + in both the primary and the secondary channel +Set to 2 if only HT STAs are associated in BSS, + however and at least one 20 MHz HT STA is associated +Set to 3 (HT mixed mode) when one or more non-HT STAs are associated + (currently non-GF HT station is considered as non-HT STA also) +*/ +int hostapd_ht_operation_update(struct hostapd_iface *iface) +{ + u16 cur_op_mode, new_op_mode; + int op_mode_changes = 0; + + if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) + return 0; + + wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X", + __func__, iface->ht_op_mode); + + if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) + && iface->num_sta_ht_no_gf) { + iface->ht_op_mode |= + HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; + op_mode_changes++; + } else if ((iface->ht_op_mode & + HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) && + iface->num_sta_ht_no_gf == 0) { + iface->ht_op_mode &= + ~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT; + op_mode_changes++; + } + + if (!(iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && + (iface->num_sta_no_ht || iface->olbc_ht)) { + iface->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; + op_mode_changes++; + } else if ((iface->ht_op_mode & + HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) && + (iface->num_sta_no_ht == 0 && !iface->olbc_ht)) { + iface->ht_op_mode &= + ~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT; + op_mode_changes++; + } + + /* Note: currently we switch to the MIXED op mode if HT non-greenfield + * station is associated. Probably it's a theoretical case, since + * it looks like all known HT STAs support greenfield. + */ + new_op_mode = 0; + if (iface->num_sta_no_ht || + (iface->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)) + new_op_mode = OP_MODE_MIXED; + else if ((iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) + && iface->num_sta_ht_20mhz) + new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED; + else if (iface->olbc_ht) + new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS; + else + new_op_mode = OP_MODE_PURE; + + cur_op_mode = iface->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK; + if (cur_op_mode != new_op_mode) { + iface->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK; + iface->ht_op_mode |= new_op_mode; + op_mode_changes++; + } + + wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d", + __func__, iface->ht_op_mode, op_mode_changes); + + return op_mode_changes; +} + + +u16 copy_sta_ht_capab(struct sta_info *sta, const u8 *ht_capab, + size_t ht_capab_len) +{ + if (!ht_capab || + ht_capab_len < sizeof(struct ieee80211_ht_capabilities)) { + sta->flags &= ~WLAN_STA_HT; + os_free(sta->ht_capabilities); + sta->ht_capabilities = NULL; + return WLAN_STATUS_SUCCESS; + } + + if (sta->ht_capabilities == NULL) { + sta->ht_capabilities = + os_zalloc(sizeof(struct ieee80211_ht_capabilities)); + if (sta->ht_capabilities == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + sta->flags |= WLAN_STA_HT; + os_memcpy(sta->ht_capabilities, ht_capab, + sizeof(struct ieee80211_ht_capabilities)); + + return WLAN_STATUS_SUCCESS; +} + + +static void update_sta_ht(struct hostapd_data *hapd, struct sta_info *sta) +{ + u16 ht_capab; + + ht_capab = le_to_host16(sta->ht_capabilities->ht_capabilities_info); + wpa_printf(MSG_DEBUG, "HT: STA " MACSTR " HT Capabilities Info: " + "0x%04x", MAC2STR(sta->addr), ht_capab); + if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) { + if (!sta->no_ht_gf_set) { + sta->no_ht_gf_set = 1; + hapd->iface->num_sta_ht_no_gf++; + } + wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no greenfield, num " + "of non-gf stations %d", + __func__, MAC2STR(sta->addr), + hapd->iface->num_sta_ht_no_gf); + } + if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) { + if (!sta->ht_20mhz_set) { + sta->ht_20mhz_set = 1; + hapd->iface->num_sta_ht_20mhz++; + } + wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - 20 MHz HT, num of " + "20MHz HT STAs %d", + __func__, MAC2STR(sta->addr), + hapd->iface->num_sta_ht_20mhz); + } +} + + +static void update_sta_no_ht(struct hostapd_data *hapd, struct sta_info *sta) +{ + if (!sta->no_ht_set) { + sta->no_ht_set = 1; + hapd->iface->num_sta_no_ht++; + } + if (hapd->iconf->ieee80211n) { + wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no HT, num of " + "non-HT stations %d", + __func__, MAC2STR(sta->addr), + hapd->iface->num_sta_no_ht); + } +} + + +void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta) +{ + if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) + update_sta_ht(hapd, sta); + else + update_sta_no_ht(hapd, sta); + + if (hostapd_ht_operation_update(hapd->iface) > 0) + ieee802_11_set_beacons(hapd->iface); +} + + +void hostapd_get_ht_capab(struct hostapd_data *hapd, + struct ieee80211_ht_capabilities *ht_cap, + struct ieee80211_ht_capabilities *neg_ht_cap) +{ + u16 cap; + + if (ht_cap == NULL) + return; + os_memcpy(neg_ht_cap, ht_cap, sizeof(*neg_ht_cap)); + cap = le_to_host16(neg_ht_cap->ht_capabilities_info); + cap &= hapd->iconf->ht_capab; + cap |= (hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_DISABLED); + + /* + * STBC needs to be handled specially + * if we don't support RX STBC, mask out TX STBC in the STA's HT caps + * if we don't support TX STBC, mask out RX STBC in the STA's HT caps + */ + if (!(hapd->iconf->ht_capab & HT_CAP_INFO_RX_STBC_MASK)) + cap &= ~HT_CAP_INFO_TX_STBC; + if (!(hapd->iconf->ht_capab & HT_CAP_INFO_TX_STBC)) + cap &= ~HT_CAP_INFO_RX_STBC_MASK; + + neg_ht_cap->ht_capabilities_info = host_to_le16(cap); +} diff --git a/contrib/wpa/hostapd/ieee802_1x.c b/contrib/wpa/src/ap/ieee802_1x.c similarity index 88% rename from contrib/wpa/hostapd/ieee802_1x.c rename to contrib/wpa/src/ap/ieee802_1x.c index 7fd80280577c..eb160f8e015c 100644 --- a/contrib/wpa/hostapd/ieee802_1x.c +++ b/contrib/wpa/src/ap/ieee802_1x.c @@ -1,6 +1,6 @@ /* * hostapd / IEEE 802.1X-2004 Authenticator - * Copyright (c) 2002-2008, Jouni Malinen + * Copyright (c) 2002-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,25 +12,28 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" -#include "hostapd.h" -#include "ieee802_1x.h" -#include "accounting.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "crypto/md5.h" +#include "crypto/crypto.h" +#include "common/ieee802_11_defs.h" +#include "common/wpa_ctrl.h" #include "radius/radius.h" #include "radius/radius_client.h" -#include "eapol_sm.h" -#include "md5.h" -#include "rc4.h" -#include "eloop.h" -#include "sta_info.h" -#include "wpa.h" -#include "preauth.h" -#include "pmksa_cache.h" -#include "driver.h" -#include "hw_features.h" #include "eap_server/eap.h" -#include "ieee802_11_defs.h" +#include "eap_common/eap_wsc_common.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "eapol_auth/eapol_auth_sm_i.h" +#include "hostapd.h" +#include "accounting.h" +#include "sta_info.h" +#include "wpa_auth.h" +#include "preauth_auth.h" +#include "pmksa_cache_auth.h" +#include "ap_config.h" +#include "ieee802_1x.h" static void ieee802_1x_finished(struct hostapd_data *hapd, @@ -67,7 +70,7 @@ static void ieee802_1x_send(struct hostapd_data *hapd, struct sta_info *sta, if (sta->flags & WLAN_STA_PREAUTH) { rsn_preauth_send(hapd, sta, buf, len); } else { - hostapd_send_eapol(hapd, sta->addr, buf, len, encrypt); + hapd->drv.send_eapol(hapd, sta->addr, buf, len, encrypt); } os_free(buf); @@ -83,15 +86,21 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, return; if (authorized) { + if (!(sta->flags & WLAN_STA_AUTHORIZED)) + wpa_msg(hapd->msg_ctx, MSG_INFO, + AP_STA_CONNECTED MACSTR, MAC2STR(sta->addr)); sta->flags |= WLAN_STA_AUTHORIZED; - res = hostapd_sta_set_flags(hapd, sta->addr, sta->flags, - WLAN_STA_AUTHORIZED, ~0); + res = hapd->drv.set_authorized(hapd, sta, 1); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_DEBUG, "authorizing port"); } else { + if ((sta->flags & (WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC)) == + (WLAN_STA_AUTHORIZED | WLAN_STA_ASSOC)) + wpa_msg(hapd->msg_ctx, MSG_INFO, + AP_STA_DISCONNECTED MACSTR, + MAC2STR(sta->addr)); sta->flags &= ~WLAN_STA_AUTHORIZED; - res = hostapd_sta_set_flags(hapd, sta->addr, sta->flags, - 0, ~WLAN_STA_AUTHORIZED); + res = hapd->drv.set_authorized(hapd, sta, 0); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_DEBUG, "unauthorizing port"); } @@ -185,6 +194,7 @@ static void ieee802_1x_tx_key_one(struct hostapd_data *hapd, } +#ifndef CONFIG_NO_VLAN static struct hostapd_wep_keys * ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname) { @@ -219,11 +229,11 @@ ieee802_1x_group_alloc(struct hostapd_data *hapd, const char *ifname) wpa_hexdump_key(MSG_DEBUG, "Default WEP key (dynamic VLAN)", key->key[key->idx], key->len[key->idx]); - if (hostapd_set_encryption(ifname, hapd, "WEP", NULL, key->idx, - key->key[key->idx], key->len[key->idx], 1)) + if (hapd->drv.set_key(ifname, hapd, WPA_ALG_WEP, NULL, key->idx, 1, + NULL, 0, key->key[key->idx], key->len[key->idx])) printf("Could not set dynamic VLAN WEP encryption key.\n"); - hostapd_set_ieee8021x(ifname, hapd, 1); + hapd->drv.set_drv_ieee8021x(hapd, ifname, 1); return key; } @@ -279,13 +289,17 @@ ieee802_1x_get_group(struct hostapd_data *hapd, struct hostapd_ssid *ssid, return ssid->dyn_vlan_keys[vlan_id]; } +#endif /* CONFIG_NO_VLAN */ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta) { - struct hostapd_wep_keys *key = NULL; + struct eapol_authenticator *eapol = hapd->eapol_auth; struct eapol_state_machine *sm = sta->eapol_sm; +#ifndef CONFIG_NO_VLAN + struct hostapd_wep_keys *key = NULL; int vlan_id; +#endif /* CONFIG_NO_VLAN */ if (sm == NULL || !sm->eap_if->eapKeyData) return; @@ -293,6 +307,7 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta) wpa_printf(MSG_DEBUG, "IEEE 802.1X: Sending EAPOL-Key(s) to " MACSTR, MAC2STR(sta->addr)); +#ifndef CONFIG_NO_VLAN vlan_id = sta->vlan_id; if (vlan_id < 0 || vlan_id > MAX_VLAN_ID) vlan_id = 0; @@ -303,9 +318,11 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta) ieee802_1x_tx_key_one(hapd, sta, key->idx, 1, key->key[key->idx], key->len[key->idx]); - } else if (hapd->default_wep_key) { - ieee802_1x_tx_key_one(hapd, sta, hapd->default_wep_key_idx, 1, - hapd->default_wep_key, + } else +#endif /* CONFIG_NO_VLAN */ + if (eapol->default_wep_key) { + ieee802_1x_tx_key_one(hapd, sta, eapol->default_wep_key_idx, 1, + eapol->default_wep_key, hapd->conf->default_wep_key_len); } @@ -328,10 +345,9 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta) /* TODO: set encryption in TX callback, i.e., only after STA * has ACKed EAPOL-Key frame */ - if (hostapd_set_encryption(hapd->conf->iface, hapd, "WEP", - sta->addr, 0, ikey, - hapd->conf->individual_wep_key_len, - 1)) { + if (hapd->drv.set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, + sta->addr, 0, 1, NULL, 0, ikey, + hapd->conf->individual_wep_key_len)) { wpa_printf(MSG_ERROR, "Could not set individual WEP " "encryption."); } @@ -343,10 +359,7 @@ void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta) const char *radius_mode_txt(struct hostapd_data *hapd) { - if (hapd->iface->current_mode == NULL) - return "802.11"; - - switch (hapd->iface->current_mode->mode) { + switch (hapd->iface->conf->hw_mode) { case HOSTAPD_MODE_IEEE80211A: return "802.11a"; case HOSTAPD_MODE_IEEE80211G: @@ -371,6 +384,7 @@ int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta) } +#ifndef CONFIG_NO_RADIUS static void ieee802_1x_learn_identity(struct hostapd_data *hapd, struct eapol_state_machine *sm, const u8 *eap, size_t len) @@ -520,7 +534,8 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd, /* State attribute must be copied if and only if this packet is * Access-Request reply to the previous Access-Challenge */ - if (sm->last_recv_radius && sm->last_recv_radius->hdr->code == + if (sm->last_recv_radius && + radius_msg_get_hdr(sm->last_recv_radius)->code == RADIUS_CODE_ACCESS_CHALLENGE) { int res = radius_msg_copy_attr(msg, sm->last_recv_radius, RADIUS_ATTR_STATE); @@ -539,30 +554,8 @@ static void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd, fail: radius_msg_free(msg); - os_free(msg); -} - - -char *eap_type_text(u8 type) -{ - switch (type) { - case EAP_TYPE_IDENTITY: return "Identity"; - case EAP_TYPE_NOTIFICATION: return "Notification"; - case EAP_TYPE_NAK: return "Nak"; - case EAP_TYPE_MD5: return "MD5-Challenge"; - case EAP_TYPE_OTP: return "One-Time Password"; - case EAP_TYPE_GTC: return "Generic Token Card"; - case EAP_TYPE_TLS: return "TLS"; - case EAP_TYPE_TTLS: return "TTLS"; - case EAP_TYPE_PEAP: return "PEAP"; - case EAP_TYPE_SIM: return "SIM"; - case EAP_TYPE_FAST: return "FAST"; - case EAP_TYPE_SAKE: return "SAKE"; - case EAP_TYPE_PSK: return "PSK"; - case EAP_TYPE_PAX: return "PAX"; - default: return "Unknown"; - } } +#endif /* CONFIG_NO_RADIUS */ static void handle_eap_response(struct hostapd_data *hapd, @@ -587,7 +580,7 @@ static void handle_eap_response(struct hostapd_data *hapd, HOSTAPD_LEVEL_DEBUG, "received EAP packet (code=%d " "id=%d len=%d) from STA: EAP Response-%s (%d)", eap->code, eap->identifier, be_to_host16(eap->length), - eap_type_text(type), type); + eap_server_get_name(0, type), type); sm->dot1xAuthEapolRespFramesRx++; @@ -647,6 +640,22 @@ static void handle_eap(struct hostapd_data *hapd, struct sta_info *sta, } +static struct eapol_state_machine * +ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta) +{ + int flags = 0; + if (sta->flags & WLAN_STA_PREAUTH) + flags |= EAPOL_SM_PREAUTH; + if (sta->wpa_sm) { + flags |= EAPOL_SM_USES_WPA; + if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) + flags |= EAPOL_SM_FROM_PMKSA_CACHE; + } + return eapol_auth_alloc(hapd->eapol_auth, sta->addr, flags, + sta->wps_ie, sta); +} + + /** * ieee802_1x_receive - Process the EAPOL frames from the Supplicant * @hapd: hostapd BSS data @@ -672,8 +681,9 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR, (unsigned long) len, MAC2STR(sa)); sta = ap_get_sta(hapd, sa); - if (!sta) { - printf(" no station information available\n"); + if (!sta || !(sta->flags & WLAN_STA_ASSOC)) { + wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not " + "associated STA"); return; } @@ -720,9 +730,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, return; if (!sta->eapol_sm) { - sta->eapol_sm = eapol_auth_alloc(hapd->eapol_auth, sta->addr, - sta->flags & WLAN_STA_PREAUTH, - sta); + sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta); if (!sta->eapol_sm) return; @@ -839,9 +847,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) if (sta->eapol_sm == NULL) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_DEBUG, "start authentication"); - sta->eapol_sm = eapol_auth_alloc(hapd->eapol_auth, sta->addr, - sta->flags & WLAN_STA_PREAUTH, - sta); + sta->eapol_sm = ieee802_1x_alloc_eapol_sm(hapd, sta); if (sta->eapol_sm == NULL) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, @@ -900,47 +906,6 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) } -void ieee802_1x_free_radius_class(struct radius_class_data *class) -{ - size_t i; - if (class == NULL) - return; - for (i = 0; i < class->count; i++) - os_free(class->attr[i].data); - os_free(class->attr); - class->attr = NULL; - class->count = 0; -} - - -int ieee802_1x_copy_radius_class(struct radius_class_data *dst, - const struct radius_class_data *src) -{ - size_t i; - - if (src->attr == NULL) - return 0; - - dst->attr = os_zalloc(src->count * sizeof(struct radius_attr_data)); - if (dst->attr == NULL) - return -1; - - dst->count = 0; - - for (i = 0; i < src->count; i++) { - dst->attr[i].data = os_malloc(src->attr[i].len); - if (dst->attr[i].data == NULL) - break; - dst->count++; - os_memcpy(dst->attr[i].data, src->attr[i].data, - src->attr[i].len); - dst->attr[i].len = src->attr[i].len; - } - - return 0; -} - - void ieee802_1x_free_station(struct sta_info *sta) { struct eapol_state_machine *sm = sta->eapol_sm; @@ -950,17 +915,17 @@ void ieee802_1x_free_station(struct sta_info *sta) sta->eapol_sm = NULL; - if (sm->last_recv_radius) { - radius_msg_free(sm->last_recv_radius); - os_free(sm->last_recv_radius); - } +#ifndef CONFIG_NO_RADIUS + radius_msg_free(sm->last_recv_radius); + radius_free_class(&sm->radius_class); +#endif /* CONFIG_NO_RADIUS */ os_free(sm->identity); - ieee802_1x_free_radius_class(&sm->radius_class); eapol_auth_free(sm); } +#ifndef CONFIG_NO_RADIUS static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, struct sta_info *sta) { @@ -1010,12 +975,14 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, if (eap_type >= 0) sm->eap_type_authsrv = eap_type; os_snprintf(buf, sizeof(buf), "EAP-Request-%s (%d)", - eap_type >= 0 ? eap_type_text(eap_type) : "??", + eap_type >= 0 ? eap_server_get_name(0, eap_type) : + "??", eap_type); break; case EAP_CODE_RESPONSE: os_snprintf(buf, sizeof(buf), "EAP Response-%s (%d)", - eap_type >= 0 ? eap_type_text(eap_type) : "??", + eap_type >= 0 ? eap_server_get_name(0, eap_type) : + "??", eap_type); break; case EAP_CODE_SUCCESS: @@ -1097,7 +1064,7 @@ static void ieee802_1x_store_radius_class(struct hostapd_data *hapd, sm == NULL) return; - ieee802_1x_free_radius_class(&sm->radius_class); + radius_free_class(&sm->radius_class); count = radius_msg_count_attr(msg, RADIUS_ATTR_CLASS, 1); if (count <= 0) return; @@ -1225,8 +1192,9 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, int session_timeout_set, old_vlanid = 0; struct eapol_state_machine *sm; int override_eapReq = 0; + struct radius_hdr *hdr = radius_msg_get_hdr(msg); - sm = ieee802_1x_search_radius_identifier(hapd, msg->hdr->identifier); + sm = ieee802_1x_search_radius_identifier(hapd, hdr->identifier); if (sm == NULL) { wpa_printf(MSG_DEBUG, "IEEE 802.1X: Could not find matching " "station for this RADIUS message"); @@ -1236,7 +1204,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, /* RFC 2869, Ch. 5.13: valid Message-Authenticator attribute MUST be * present when packet contains an EAP-Message attribute */ - if (msg->hdr->code == RADIUS_CODE_ACCESS_REJECT && + if (hdr->code == RADIUS_CODE_ACCESS_REJECT && radius_msg_get_attr(msg, RADIUS_ATTR_MESSAGE_AUTHENTICATOR, NULL, 0) < 0 && radius_msg_get_attr(msg, RADIUS_ATTR_EAP_MESSAGE, NULL, 0) < 0) { @@ -1250,9 +1218,9 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, return RADIUS_RX_INVALID_AUTHENTICATOR; } - if (msg->hdr->code != RADIUS_CODE_ACCESS_ACCEPT && - msg->hdr->code != RADIUS_CODE_ACCESS_REJECT && - msg->hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) { + if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT && + hdr->code != RADIUS_CODE_ACCESS_REJECT && + hdr->code != RADIUS_CODE_ACCESS_CHALLENGE) { printf("Unknown RADIUS message code\n"); return RADIUS_RX_UNKNOWN; } @@ -1261,11 +1229,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, wpa_printf(MSG_DEBUG, "RADIUS packet matching with station " MACSTR, MAC2STR(sta->addr)); - if (sm->last_recv_radius) { - radius_msg_free(sm->last_recv_radius); - os_free(sm->last_recv_radius); - } - + radius_msg_free(sm->last_recv_radius); sm->last_recv_radius = msg; session_timeout_set = @@ -1275,8 +1239,8 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, &termination_action)) termination_action = RADIUS_TERMINATION_ACTION_DEFAULT; - if (hapd->conf->radius->acct_interim_interval == 0 && - msg->hdr->code == RADIUS_CODE_ACCESS_ACCEPT && + if (hapd->conf->acct_interim_interval == 0 && + hdr->code == RADIUS_CODE_ACCESS_ACCEPT && radius_msg_get_attr_int32(msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, &acct_interim_interval) == 0) { if (acct_interim_interval < 60) { @@ -1291,10 +1255,11 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, } - switch (msg->hdr->code) { + switch (hdr->code) { case RADIUS_CODE_ACCESS_ACCEPT: if (sta->ssid->dynamic_vlan == DYNAMIC_VLAN_DISABLED) sta->vlan_id = 0; +#ifndef CONFIG_NO_VLAN else { old_vlanid = sta->vlan_id; sta->vlan_id = radius_msg_get_vlanid(msg); @@ -1315,8 +1280,10 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, "ID in Access-Accept"); break; } +#endif /* CONFIG_NO_VLAN */ - ap_sta_bind_vlan(hapd, sta, old_vlanid); + if (ap_sta_bind_vlan(hapd, sta, old_vlanid) < 0) + break; /* RFC 3580, Ch. 3.17 */ if (session_timeout_set && termination_action == @@ -1373,6 +1340,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, return RADIUS_RX_QUEUED; } +#endif /* CONFIG_NO_RADIUS */ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta) @@ -1384,11 +1352,10 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta) hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_DEBUG, "aborting authentication"); - if (sm->last_recv_radius) { - radius_msg_free(sm->last_recv_radius); - os_free(sm->last_recv_radius); - sm->last_recv_radius = NULL; - } +#ifndef CONFIG_NO_RADIUS + radius_msg_free(sm->last_recv_radius); + sm->last_recv_radius = NULL; +#endif /* CONFIG_NO_RADIUS */ if (sm->eap_if->eapTimeout) { /* @@ -1397,74 +1364,32 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta) * could only be sent if the EAP peer actually replied). */ sm->eap_if->portEnabled = FALSE; - hostapd_sta_deauth(hapd, sta->addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | - WLAN_STA_AUTHORIZED); - eloop_cancel_timeout(ap_handle_timer, hapd, sta); - eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta); - sta->timeout_next = STA_REMOVE; + ap_sta_disconnect(hapd, sta, sta->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); } } -#ifdef HOSTAPD_DUMP_STATE -static void fprint_char(FILE *f, char c) -{ - if (c >= 32 && c < 127) - fprintf(f, "%c", c); - else - fprintf(f, "<%02x>", c); -} - - -void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta) -{ - struct eapol_state_machine *sm = sta->eapol_sm; - if (sm == NULL) - return; - - fprintf(f, "%sIEEE 802.1X:\n", prefix); - - if (sm->identity) { - size_t i; - fprintf(f, "%sidentity=", prefix); - for (i = 0; i < sm->identity_len; i++) - fprint_char(f, sm->identity[i]); - fprintf(f, "\n"); - } - - fprintf(f, "%slast EAP type: Authentication Server: %d (%s) " - "Supplicant: %d (%s)\n", prefix, - sm->eap_type_authsrv, eap_type_text(sm->eap_type_authsrv), - sm->eap_type_supp, eap_type_text(sm->eap_type_supp)); - - fprintf(f, "%scached_packets=%s\n", prefix, - sm->last_recv_radius ? "[RX RADIUS]" : ""); - - eapol_auth_dump_state(f, prefix, sm); -} -#endif /* HOSTAPD_DUMP_STATE */ - - static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd) { + struct eapol_authenticator *eapol = hapd->eapol_auth; + if (hapd->conf->default_wep_key_len < 1) return 0; - os_free(hapd->default_wep_key); - hapd->default_wep_key = os_malloc(hapd->conf->default_wep_key_len); - if (hapd->default_wep_key == NULL || - os_get_random(hapd->default_wep_key, + os_free(eapol->default_wep_key); + eapol->default_wep_key = os_malloc(hapd->conf->default_wep_key_len); + if (eapol->default_wep_key == NULL || + os_get_random(eapol->default_wep_key, hapd->conf->default_wep_key_len)) { printf("Could not generate random WEP key.\n"); - os_free(hapd->default_wep_key); - hapd->default_wep_key = NULL; + os_free(eapol->default_wep_key); + eapol->default_wep_key = NULL; return -1; } wpa_hexdump_key(MSG_DEBUG, "IEEE 802.1X: New default WEP key", - hapd->default_wep_key, + eapol->default_wep_key, hapd->conf->default_wep_key_len); return 0; @@ -1485,36 +1410,37 @@ static int ieee802_1x_sta_key_available(struct hostapd_data *hapd, static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx) { struct hostapd_data *hapd = eloop_ctx; + struct eapol_authenticator *eapol = hapd->eapol_auth; - if (hapd->default_wep_key_idx >= 3) - hapd->default_wep_key_idx = + if (eapol->default_wep_key_idx >= 3) + eapol->default_wep_key_idx = hapd->conf->individual_wep_key_len > 0 ? 1 : 0; else - hapd->default_wep_key_idx++; + eapol->default_wep_key_idx++; wpa_printf(MSG_DEBUG, "IEEE 802.1X: New default WEP key index %d", - hapd->default_wep_key_idx); + eapol->default_wep_key_idx); if (ieee802_1x_rekey_broadcast(hapd)) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_WARNING, "failed to generate a " "new broadcast key"); - os_free(hapd->default_wep_key); - hapd->default_wep_key = NULL; + os_free(eapol->default_wep_key); + eapol->default_wep_key = NULL; return; } /* TODO: Could setup key for RX here, but change default TX keyid only * after new broadcast key has been sent to all stations. */ - if (hostapd_set_encryption(hapd->conf->iface, hapd, "WEP", NULL, - hapd->default_wep_key_idx, - hapd->default_wep_key, - hapd->conf->default_wep_key_len, 1)) { + if (hapd->drv.set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, NULL, + eapol->default_wep_key_idx, 1, NULL, 0, + eapol->default_wep_key, + hapd->conf->default_wep_key_len)) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_WARNING, "failed to configure a " "new broadcast key"); - os_free(hapd->default_wep_key); - hapd->default_wep_key = NULL; + os_free(eapol->default_wep_key); + eapol->default_wep_key = NULL; return; } @@ -1530,6 +1456,30 @@ static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx) static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type, const u8 *data, size_t datalen) { +#ifdef CONFIG_WPS + struct sta_info *sta = sta_ctx; + + if ((sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)) == + WLAN_STA_MAYBE_WPS) { + const u8 *identity; + size_t identity_len; + struct eapol_state_machine *sm = sta->eapol_sm; + + identity = eap_get_identity(sm->eap, &identity_len); + if (identity && + ((identity_len == WSC_ID_ENROLLEE_LEN && + os_memcmp(identity, WSC_ID_ENROLLEE, + WSC_ID_ENROLLEE_LEN) == 0) || + (identity_len == WSC_ID_REGISTRAR_LEN && + os_memcmp(identity, WSC_ID_REGISTRAR, + WSC_ID_REGISTRAR_LEN) == 0))) { + wpa_printf(MSG_DEBUG, "WPS: WLAN_STA_MAYBE_WPS -> " + "WLAN_STA_WPS"); + sta->flags |= WLAN_STA_WPS; + } + } +#endif /* CONFIG_WPS */ + ieee802_1x_send(ctx, sta_ctx, type, data, datalen); } @@ -1537,10 +1487,12 @@ static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type, static void ieee802_1x_aaa_send(void *ctx, void *sta_ctx, const u8 *data, size_t datalen) { +#ifndef CONFIG_NO_RADIUS struct hostapd_data *hapd = ctx; struct sta_info *sta = sta_ctx; ieee802_1x_encapsulate_radius(hapd, sta, data, datalen); +#endif /* CONFIG_NO_RADIUS */ } @@ -1608,6 +1560,7 @@ static int ieee802_1x_sta_entry_alive(void *ctx, const u8 *addr) static void ieee802_1x_logger(void *ctx, const u8 *addr, eapol_logger_level level, const char *txt) { +#ifndef CONFIG_NO_HOSTAPD_LOGGER struct hostapd_data *hapd = ctx; int hlevel; @@ -1626,6 +1579,7 @@ static void ieee802_1x_logger(void *ctx, const u8 *addr, hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE8021X, hlevel, "%s", txt); +#endif /* CONFIG_NO_HOSTAPD_LOGGER */ } @@ -1654,6 +1608,22 @@ static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx) } +static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx, + enum eapol_event type) +{ + /* struct hostapd_data *hapd = ctx; */ + struct sta_info *sta = sta_ctx; + switch (type) { + case EAPOL_AUTH_SM_CHANGE: + wpa_auth_sm_notify(sta->wpa_sm); + break; + case EAPOL_AUTH_REAUTHENTICATE: + wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL); + break; + } +} + + int ieee802_1x_init(struct hostapd_data *hapd) { int i; @@ -1661,12 +1631,13 @@ int ieee802_1x_init(struct hostapd_data *hapd) struct eapol_auth_cb cb; os_memset(&conf, 0, sizeof(conf)); - conf.hapd = hapd; + conf.ctx = hapd; conf.eap_reauth_period = hapd->conf->eap_reauth_period; conf.wpa = hapd->conf->wpa; conf.individual_wep_key_len = hapd->conf->individual_wep_key_len; conf.eap_server = hapd->conf->eap_server; conf.ssl_ctx = hapd->ssl_ctx; + conf.msg_ctx = hapd->msg_ctx; conf.eap_sim_db_priv = hapd->eap_sim_db_priv; conf.eap_req_id_text = hapd->conf->eap_req_id_text; conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len; @@ -1691,29 +1662,31 @@ int ieee802_1x_init(struct hostapd_data *hapd) cb.set_port_authorized = ieee802_1x_set_port_authorized; cb.abort_auth = _ieee802_1x_abort_auth; cb.tx_key = _ieee802_1x_tx_key; + cb.eapol_event = ieee802_1x_eapol_event; hapd->eapol_auth = eapol_auth_init(&conf, &cb); if (hapd->eapol_auth == NULL) return -1; if ((hapd->conf->ieee802_1x || hapd->conf->wpa) && - hostapd_set_ieee8021x(hapd->conf->iface, hapd, 1)) + hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 1)) return -1; +#ifndef CONFIG_NO_RADIUS if (radius_client_register(hapd->radius, RADIUS_AUTH, ieee802_1x_receive_auth, hapd)) return -1; +#endif /* CONFIG_NO_RADIUS */ if (hapd->conf->default_wep_key_len) { - hostapd_set_privacy(hapd, 1); - for (i = 0; i < 4; i++) - hostapd_set_encryption(hapd->conf->iface, hapd, - "none", NULL, i, NULL, 0, 0); + hapd->drv.set_key(hapd->conf->iface, hapd, + WPA_ALG_NONE, NULL, i, 0, NULL, 0, + NULL, 0); ieee802_1x_rekey(hapd, NULL); - if (hapd->default_wep_key == NULL) + if (hapd->eapol_auth->default_wep_key == NULL) return -1; } @@ -1727,24 +1700,15 @@ void ieee802_1x_deinit(struct hostapd_data *hapd) if (hapd->driver != NULL && (hapd->conf->ieee802_1x || hapd->conf->wpa)) - hostapd_set_ieee8021x(hapd->conf->iface, hapd, 0); + hapd->drv.set_drv_ieee8021x(hapd, hapd->conf->iface, 0); eapol_auth_deinit(hapd->eapol_auth); hapd->eapol_auth = NULL; } -int ieee802_1x_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss) -{ - ieee802_1x_deinit(hapd); - return ieee802_1x_init(hapd); -} - - int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, - u8 *buf, size_t len, int ack) + const u8 *buf, size_t len, int ack) { struct ieee80211_hdr *hdr; struct ieee802_1x_hdr *xhdr; @@ -2039,4 +2003,23 @@ static void ieee802_1x_finished(struct hostapd_data *hapd, HOSTAPD_LEVEL_DEBUG, "Added PMKSA cache entry (IEEE 802.1X)"); } + +#ifdef CONFIG_WPS + if (!success && (sta->flags & WLAN_STA_WPS)) { + /* + * Many devices require deauthentication after WPS provisioning + * and some may not be be able to do that themselves, so + * disconnect the client here. + */ + wpa_printf(MSG_DEBUG, "WPS: Force disconnection after " + "EAP-Failure"); + /* Add a small sleep to increase likelihood of previously + * requested EAP-Failure TX getting out before this should the + * driver reorder operations. + */ + os_sleep(0, 10000); + ap_sta_disconnect(hapd, sta, sta->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + } +#endif /* CONFIG_WPS */ } diff --git a/contrib/wpa/hostapd/ieee802_1x.h b/contrib/wpa/src/ap/ieee802_1x.h similarity index 89% rename from contrib/wpa/hostapd/ieee802_1x.h rename to contrib/wpa/src/ap/ieee802_1x.h index 94cff9356372..1a4d2eb0f2c1 100644 --- a/contrib/wpa/hostapd/ieee802_1x.h +++ b/contrib/wpa/src/ap/ieee802_1x.h @@ -21,6 +21,10 @@ struct eapol_state_machine; struct hostapd_config; struct hostapd_bss_config; +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif /* _MSC_VER */ + /* RFC 3580, 4. RC4 EAPOL-Key Frame */ struct ieee802_1x_eapol_key { @@ -43,7 +47,11 @@ struct ieee802_1x_eapol_key { * represents the number of least significant octets from * MS-MPPE-Send-Key attribute to be used as the keying material; * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */ -} __attribute__ ((packed)); +} STRUCT_PACKED; + +#ifdef _MSC_VER +#pragma pack(pop) +#endif /* _MSC_VER */ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, @@ -58,11 +66,8 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta); int ieee802_1x_init(struct hostapd_data *hapd); void ieee802_1x_deinit(struct hostapd_data *hapd); -int ieee802_1x_reconfig(struct hostapd_data *hapd, - struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss); int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, - u8 *buf, size_t len, int ack); + const u8 *buf, size_t len, int ack); u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len); u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len, int idx); @@ -78,12 +83,6 @@ int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, void hostapd_get_ntp_timestamp(u8 *buf); char *eap_type_text(u8 type); -struct radius_class_data; - -void ieee802_1x_free_radius_class(struct radius_class_data *class); -int ieee802_1x_copy_radius_class(struct radius_class_data *dst, - const struct radius_class_data *src); - const char *radius_mode_txt(struct hostapd_data *hapd); int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta); diff --git a/contrib/wpa/hostapd/peerkey.c b/contrib/wpa/src/ap/peerkey_auth.c similarity index 98% rename from contrib/wpa/hostapd/peerkey.c rename to contrib/wpa/src/ap/peerkey_auth.c index 83f3ce513de3..f68c47909ae6 100644 --- a/contrib/wpa/hostapd/peerkey.c +++ b/contrib/wpa/src/ap/peerkey_auth.c @@ -1,6 +1,6 @@ /* * hostapd - PeerKey for Direct Link Setup (DLS) - * Copyright (c) 2006-2008, Jouni Malinen + * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,14 +12,13 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" -#include "common.h" -#include "eloop.h" -#include "sha1.h" -#include "sha256.h" -#include "wpa.h" -#include "defs.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "wpa_auth.h" #include "wpa_auth_i.h" #include "wpa_auth_ie.h" diff --git a/contrib/wpa/hostapd/pmksa_cache.c b/contrib/wpa/src/ap/pmksa_cache_auth.c similarity index 79% rename from contrib/wpa/hostapd/pmksa_cache.c rename to contrib/wpa/src/ap/pmksa_cache_auth.c index 5f54a34c11d4..22f44b78464a 100644 --- a/contrib/wpa/hostapd/pmksa_cache.c +++ b/contrib/wpa/src/ap/pmksa_cache_auth.c @@ -12,18 +12,15 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" -#include "common.h" -#include "ap.h" -#include "config.h" -#include "common.h" -#include "eloop.h" -#include "sha1.h" -#include "sha256.h" -#include "ieee802_1x.h" -#include "eapol_sm.h" -#include "pmksa_cache.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "eapol_auth/eapol_auth_sm_i.h" +#include "sta_info.h" +#include "ap_config.h" +#include "pmksa_cache_auth.h" static const int pmksa_cache_max_entries = 1024; @@ -41,40 +38,6 @@ struct rsn_pmksa_cache { }; -/** - * rsn_pmkid - Calculate PMK identifier - * @pmk: Pairwise master key - * @pmk_len: Length of pmk in bytes - * @aa: Authenticator address - * @spa: Supplicant address - * @pmkid: Buffer for PMKID - * @use_sha256: Whether to use SHA256-based KDF - * - * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy - * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) - */ -void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, - u8 *pmkid, int use_sha256) -{ - char *title = "PMK Name"; - const u8 *addr[3]; - const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; - unsigned char hash[SHA256_MAC_LEN]; - - addr[0] = (u8 *) title; - addr[1] = aa; - addr[2] = spa; - -#ifdef CONFIG_IEEE80211W - if (use_sha256) - hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); - else -#endif /* CONFIG_IEEE80211W */ - hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); - os_memcpy(pmkid, hash, PMKID_LEN); -} - - static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa); @@ -83,7 +46,9 @@ static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry) if (entry == NULL) return; os_free(entry->identity); - ieee802_1x_free_radius_class(&entry->radius_class); +#ifndef CONFIG_NO_RADIUS + radius_free_class(&entry->radius_class); +#endif /* CONFIG_NO_RADIUS */ os_free(entry); } @@ -177,11 +142,12 @@ static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry, } } - ieee802_1x_copy_radius_class(&entry->radius_class, - &eapol->radius_class); +#ifndef CONFIG_NO_RADIUS + radius_copy_class(&entry->radius_class, &eapol->radius_class); +#endif /* CONFIG_NO_RADIUS */ entry->eap_type_authsrv = eapol->eap_type_authsrv; - entry->vlan_id = eapol->sta->vlan_id; + entry->vlan_id = ((struct sta_info *) eapol->sta)->vlan_id; } @@ -203,16 +169,17 @@ void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry, eapol->identity, eapol->identity_len); } - ieee802_1x_free_radius_class(&eapol->radius_class); - ieee802_1x_copy_radius_class(&eapol->radius_class, - &entry->radius_class); +#ifndef CONFIG_NO_RADIUS + radius_free_class(&eapol->radius_class); + radius_copy_class(&eapol->radius_class, &entry->radius_class); +#endif /* CONFIG_NO_RADIUS */ if (eapol->radius_class.attr) { wpa_printf(MSG_DEBUG, "Copied %lu Class attribute(s) from " "PMKSA", (unsigned long) eapol->radius_class.count); } eapol->eap_type_authsrv = entry->eap_type_authsrv; - eapol->sta->vlan_id = entry->vlan_id; + ((struct sta_info *) eapol->sta)->vlan_id = entry->vlan_id; } @@ -248,8 +215,8 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa, /** - * pmksa_cache_add - Add a PMKSA cache entry - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() + * pmksa_cache_auth_add - Add a PMKSA cache entry + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() * @pmk: The new pairwise master key * @pmk_len: PMK length in bytes, usually PMK_LEN (32) * @aa: Authenticator address @@ -265,7 +232,8 @@ static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa, * based on the PMK. */ struct rsn_pmksa_cache_entry * -pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, +pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, + const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, int session_timeout, struct eapol_state_machine *eapol, int akmp) { @@ -294,7 +262,7 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, /* Replace an old entry for the same STA (if found) with the new entry */ - pos = pmksa_cache_get(pmksa, spa, NULL); + pos = pmksa_cache_auth_get(pmksa, spa, NULL); if (pos) pmksa_cache_free_entry(pmksa, pos); @@ -337,8 +305,9 @@ pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa, old_entry->identity_len); } } - ieee802_1x_copy_radius_class(&entry->radius_class, - &old_entry->radius_class); +#ifndef CONFIG_NO_RADIUS + radius_copy_class(&entry->radius_class, &old_entry->radius_class); +#endif /* CONFIG_NO_RADIUS */ entry->eap_type_authsrv = old_entry->eap_type_authsrv; entry->vlan_id = old_entry->vlan_id; entry->opportunistic = 1; @@ -350,10 +319,10 @@ pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa, /** - * pmksa_cache_deinit - Free all entries in PMKSA cache - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() + * pmksa_cache_auth_deinit - Free all entries in PMKSA cache + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() */ -void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) +void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa) { struct rsn_pmksa_cache_entry *entry, *prev; int i; @@ -375,14 +344,15 @@ void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) /** - * pmksa_cache_get - Fetch a PMKSA cache entry - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() + * pmksa_cache_auth_get - Fetch a PMKSA cache entry + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() * @spa: Supplicant address or %NULL to match any * @pmkid: PMKID or %NULL to match any * Returns: Pointer to PMKSA cache entry or %NULL if no match was found */ -struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, - const u8 *spa, const u8 *pmkid) +struct rsn_pmksa_cache_entry * +pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa, + const u8 *spa, const u8 *pmkid) { struct rsn_pmksa_cache_entry *entry; @@ -404,7 +374,7 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, /** * pmksa_cache_get_okc - Fetch a PMKSA cache entry using OKC - * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() * @aa: Authenticator address * @spa: Supplicant address * @pmkid: PMKID @@ -434,14 +404,14 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc( /** - * pmksa_cache_init - Initialize PMKSA cache + * pmksa_cache_auth_init - Initialize PMKSA cache * @free_cb: Callback function to be called when a PMKSA cache entry is freed * @ctx: Context pointer for free_cb function * Returns: Pointer to PMKSA cache data or %NULL on failure */ struct rsn_pmksa_cache * -pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx), void *ctx) +pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, + void *ctx), void *ctx) { struct rsn_pmksa_cache *pmksa; diff --git a/contrib/wpa/hostapd/pmksa_cache.h b/contrib/wpa/src/ap/pmksa_cache_auth.h similarity index 71% rename from contrib/wpa/hostapd/pmksa_cache.h rename to contrib/wpa/src/ap/pmksa_cache_auth.h index 6ba2da6073eb..9628b13da029 100644 --- a/contrib/wpa/hostapd/pmksa_cache.h +++ b/contrib/wpa/src/ap/pmksa_cache_auth.h @@ -15,6 +15,8 @@ #ifndef PMKSA_CACHE_H #define PMKSA_CACHE_H +#include "radius/radius.h" + /** * struct rsn_pmksa_cache_entry - PMKSA cache entry */ @@ -38,25 +40,25 @@ struct rsn_pmksa_cache_entry { struct rsn_pmksa_cache; struct rsn_pmksa_cache * -pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, - void *ctx), void *ctx); -void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa); -struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, - const u8 *spa, const u8 *pmkid); +pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, + void *ctx), void *ctx); +void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa); +struct rsn_pmksa_cache_entry * +pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa, + const u8 *spa, const u8 *pmkid); struct rsn_pmksa_cache_entry * pmksa_cache_get_okc( struct rsn_pmksa_cache *pmksa, const u8 *spa, const u8 *aa, const u8 *pmkid); struct rsn_pmksa_cache_entry * -pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, - const u8 *aa, const u8 *spa, int session_timeout, - struct eapol_state_machine *eapol, int akmp); +pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, + const u8 *pmk, size_t pmk_len, + const u8 *aa, const u8 *spa, int session_timeout, + struct eapol_state_machine *eapol, int akmp); struct rsn_pmksa_cache_entry * pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa, const struct rsn_pmksa_cache_entry *old_entry, const u8 *aa, const u8 *pmkid); void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry, struct eapol_state_machine *eapol); -void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, - u8 *pmkid, int use_sha256); #endif /* PMKSA_CACHE_H */ diff --git a/contrib/wpa/hostapd/preauth.c b/contrib/wpa/src/ap/preauth_auth.c similarity index 95% rename from contrib/wpa/hostapd/preauth.c rename to contrib/wpa/src/ap/preauth_auth.c index 9ab41eda0bee..8e133158a976 100644 --- a/contrib/wpa/hostapd/preauth.c +++ b/contrib/wpa/src/ap/preauth_auth.c @@ -12,19 +12,22 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" #ifdef CONFIG_RSN_PREAUTH -#include "hostapd.h" +#include "utils/common.h" +#include "utils/eloop.h" #include "l2_packet/l2_packet.h" +#include "common/wpa_common.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "eapol_auth/eapol_auth_sm_i.h" +#include "hostapd.h" +#include "ap_config.h" #include "ieee802_1x.h" -#include "eloop.h" #include "sta_info.h" -#include "wpa_common.h" -#include "eapol_sm.h" -#include "wpa.h" -#include "preauth.h" +#include "wpa_auth.h" +#include "preauth_auth.h" #ifndef ETH_P_PREAUTH #define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ @@ -256,7 +259,7 @@ void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta, os_memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN); os_memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN); - ethhdr->h_proto = htons(ETH_P_PREAUTH); + ethhdr->h_proto = host_to_be16(ETH_P_PREAUTH); os_memcpy(ethhdr + 1, buf, len); if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr, diff --git a/contrib/wpa/hostapd/preauth.h b/contrib/wpa/src/ap/preauth_auth.h similarity index 100% rename from contrib/wpa/hostapd/preauth.h rename to contrib/wpa/src/ap/preauth_auth.h diff --git a/contrib/wpa/hostapd/sta_info.c b/contrib/wpa/src/ap/sta_info.c similarity index 88% rename from contrib/wpa/hostapd/sta_info.c rename to contrib/wpa/src/ap/sta_info.c index a139ba9bdf94..335c9a5bd724 100644 --- a/contrib/wpa/hostapd/sta_info.c +++ b/contrib/wpa/src/ap/sta_info.c @@ -1,7 +1,6 @@ /* * hostapd / Station table - * Copyright (c) 2002-2008, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation + * Copyright (c) 2002-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,26 +12,28 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "radius/radius.h" +#include "radius/radius_client.h" +#include "drivers/driver.h" #include "hostapd.h" -#include "sta_info.h" -#include "eloop.h" #include "accounting.h" #include "ieee802_1x.h" #include "ieee802_11.h" -#include "radius/radius.h" -#include "wpa.h" -#include "preauth.h" -#include "radius/radius_client.h" -#include "driver.h" +#include "wpa_auth.h" +#include "preauth_auth.h" +#include "ap_config.h" #include "beacon.h" -#include "hw_features.h" -#include "mlme.h" +#include "ap_mlme.h" #include "vlan_init.h" +#include "sta_info.h" -static int ap_sta_in_other_bss(struct hostapd_data *hapd, - struct sta_info *sta, u32 flags); +static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, + struct sta_info *sta); static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx); #ifdef CONFIG_IEEE80211W static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx); @@ -120,15 +121,18 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) accounting_sta_stop(hapd, sta); - if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC) && - !(sta->flags & WLAN_STA_PREAUTH)) - hostapd_sta_remove(hapd, sta->addr); + if (sta->flags & WLAN_STA_WDS) + hapd->drv.set_wds_sta(hapd, sta->addr, sta->aid, 0); + + if (!(sta->flags & WLAN_STA_PREAUTH)) + hapd->drv.sta_remove(hapd, sta->addr); ap_sta_hash_del(hapd, sta); ap_sta_list_del(hapd, sta); if (sta->aid > 0) - hapd->sta_aid[sta->aid - 1] = NULL; + hapd->sta_aid[(sta->aid - 1) / 32] &= + ~BIT((sta->aid - 1) % 32); hapd->num_sta--; if (sta->nonerp_set) { @@ -154,7 +158,6 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) set_beacon++; } -#ifdef CONFIG_IEEE80211N if (sta->no_ht_gf_set) { sta->no_ht_gf_set = 0; hapd->iface->num_sta_ht_no_gf--; @@ -170,9 +173,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) hapd->iface->num_sta_ht_20mhz--; } +#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N) if (hostapd_ht_operation_update(hapd->iface) > 0) set_beacon++; -#endif /* CONFIG_IEEE80211N */ +#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */ if (set_beacon) ieee802_11_set_beacons(hapd->iface); @@ -183,7 +187,9 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) ieee802_1x_free_station(sta); wpa_auth_sta_deinit(sta->wpa_sm); rsn_preauth_free_station(hapd, sta); +#ifndef CONFIG_NO_RADIUS radius_client_flush_auth(hapd->radius, sta->addr); +#endif /* CONFIG_NO_RADIUS */ os_free(sta->last_assoc_req); os_free(sta->challenge); @@ -195,6 +201,8 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) wpabuf_free(sta->wps_ie); + os_free(sta->ht_capabilities); + os_free(sta); } @@ -247,7 +255,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) int inactive_sec; wpa_printf(MSG_DEBUG, "Checking STA " MACSTR " inactivity:", MAC2STR(sta->addr)); - inactive_sec = hostapd_get_inact_sec(hapd, sta->addr); + inactive_sec = hapd->drv.get_inact_sec(hapd, sta->addr); if (inactive_sec == -1) { wpa_printf(MSG_DEBUG, "Could not get station info " "from kernel driver for " MACSTR ".", @@ -280,6 +288,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) if (sta->timeout_next == STA_NULLFUNC && (sta->flags & WLAN_STA_ASSOC)) { +#ifndef CONFIG_NATIVE_WINDOWS /* send data frame to poll STA and check whether this frame * is ACKed */ struct ieee80211_hdr hdr; @@ -287,7 +296,6 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) wpa_printf(MSG_DEBUG, " Polling STA with data frame"); sta->flags |= WLAN_STA_PENDING_POLL; -#ifndef CONFIG_NATIVE_WINDOWS os_memset(&hdr, 0, sizeof(hdr)); if (hapd->driver && os_strcmp(hapd->driver->name, "hostap") == 0) { @@ -311,7 +319,7 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) ETH_ALEN); os_memcpy(hdr.IEEE80211_SA_FROMDS, hapd->own_addr, ETH_ALEN); - if (hostapd_send_mgmt_frame(hapd, &hdr, sizeof(hdr), 0) < 0) + if (hapd->drv.send_mgmt_frame(hapd, &hdr, sizeof(hdr)) < 0) perror("ap_handle_timer: send"); #endif /* CONFIG_NATIVE_WINDOWS */ } else if (sta->timeout_next != STA_REMOVE) { @@ -322,10 +330,10 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) MAC2STR(sta->addr)); if (deauth) { - hostapd_sta_deauth(hapd, sta->addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); + hapd->drv.sta_deauth(hapd, sta->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); } else { - hostapd_sta_disassoc( + hapd->drv.sta_disassoc( hapd, sta->addr, WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); } @@ -389,7 +397,7 @@ static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx) RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT; os_memcpy(addr, sta->addr, ETH_ALEN); ap_free_sta(hapd, sta); - hostapd_sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); + hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); } @@ -432,7 +440,7 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr) wpa_printf(MSG_ERROR, "malloc failed"); return NULL; } - sta->acct_interim_interval = hapd->conf->radius->acct_interim_interval; + sta->acct_interim_interval = hapd->conf->acct_interim_interval; /* initialize STA info data */ eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, @@ -443,6 +451,7 @@ struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr) hapd->num_sta++; ap_sta_hash_add(hapd, sta); sta->ssid = &hapd->conf->ssid; + ap_sta_remove_in_other_bss(hapd, sta); return sta; } @@ -454,7 +463,7 @@ static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta) wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver", MAC2STR(sta->addr)); - if (hostapd_sta_remove(hapd, sta->addr) && + if (hapd->drv.sta_remove(hapd, sta->addr) && sta->flags & WLAN_STA_ASSOC) { wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR " from kernel driver.", MAC2STR(sta->addr)); @@ -464,8 +473,8 @@ static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta) } -static int ap_sta_in_other_bss(struct hostapd_data *hapd, - struct sta_info *sta, u32 flags) +static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, + struct sta_info *sta) { struct hostapd_iface *iface = hapd->iface; size_t i; @@ -480,11 +489,12 @@ static int ap_sta_in_other_bss(struct hostapd_data *hapd, if (bss == hapd || bss == NULL) continue; sta2 = ap_get_sta(bss, sta->addr); - if (sta2 && ((sta2->flags & flags) == flags)) - return 1; - } + if (!sta2) + continue; - return 0; + ap_sta_disconnect(bss, sta2, sta2->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + } } @@ -494,8 +504,7 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR, hapd->conf->iface, MAC2STR(sta->addr)); sta->flags &= ~WLAN_STA_ASSOC; - if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC)) - ap_sta_remove(hapd, sta); + ap_sta_remove(hapd, sta); sta->timeout_next = STA_DEAUTH; eloop_cancel_timeout(ap_handle_timer, hapd, sta); eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0, @@ -513,8 +522,7 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR, hapd->conf->iface, MAC2STR(sta->addr)); sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - if (!ap_sta_in_other_bss(hapd, sta, WLAN_STA_ASSOC)) - ap_sta_remove(hapd, sta); + ap_sta_remove(hapd, sta); sta->timeout_next = STA_REMOVE; eloop_cancel_timeout(ap_handle_timer, hapd, sta); eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, @@ -529,8 +537,10 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, int old_vlanid) { +#ifndef CONFIG_NO_VLAN const char *iface; struct hostapd_vlan *vlan = NULL; + int ret; /* * Do not proceed furthur if the vlan id remains same. We do not want @@ -626,7 +636,16 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0) wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA"); - return hostapd_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id); + ret = hapd->drv.set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id); + if (ret < 0) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "could not bind the STA " + "entry to vlan_id=%d", sta->vlan_id); + } + return ret; +#else /* CONFIG_NO_VLAN */ + return 0; +#endif /* CONFIG_NO_VLAN */ } @@ -690,7 +709,9 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx) HOSTAPD_LEVEL_DEBUG, "association SA Query attempt %d", sta->sa_query_count); +#ifdef NEED_AP_MLME ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id); +#endif /* NEED_AP_MLME */ } @@ -709,3 +730,22 @@ void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta) } #endif /* CONFIG_IEEE80211W */ + + +void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *addr, u16 reason) +{ + + if (sta == NULL && addr) + sta = ap_get_sta(hapd, addr); + + if (addr) + hapd->drv.sta_deauth(hapd, addr, reason); + + if (sta == NULL) + return; + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_AUTHORIZED); + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(0, 0, ap_handle_timer, hapd, sta); + sta->timeout_next = STA_REMOVE; +} diff --git a/contrib/wpa/hostapd/ap.h b/contrib/wpa/src/ap/sta_info.h similarity index 68% rename from contrib/wpa/hostapd/ap.h rename to contrib/wpa/src/ap/sta_info.h index 2c6d7e9799cd..55faa5a28c5e 100644 --- a/contrib/wpa/hostapd/ap.h +++ b/contrib/wpa/src/ap/sta_info.h @@ -1,7 +1,6 @@ /* - * hostapd / Station table data structures - * Copyright (c) 2002-2008, Jouni Malinen - * Copyright (c) 2007-2008, Intel Corporation + * hostapd / Station table + * Copyright (c) 2002-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,12 +12,8 @@ * See README and COPYING for more details. */ -#ifndef AP_H -#define AP_H - -#ifdef CONFIG_IEEE80211N -#include "ieee802_11_defs.h" -#endif /* CONFIG_IEEE80211N */ +#ifndef STA_INFO_H +#define STA_INFO_H /* STA flags */ #define WLAN_STA_AUTH BIT(0) @@ -35,6 +30,7 @@ #define WLAN_STA_HT BIT(11) #define WLAN_STA_WPS BIT(12) #define WLAN_STA_MAYBE_WPS BIT(13) +#define WLAN_STA_WDS BIT(14) #define WLAN_STA_NONERP BIT(31) /* Maximum number of supported rates (from both Supported Rates and Extended @@ -47,7 +43,7 @@ struct sta_info { struct sta_info *hnext; /* next entry in hash table list */ u8 addr[6]; u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */ - u32 flags; + u32 flags; /* Bitfield of WLAN_STA_* */ u16 capability; u16 listen_interval; /* or beacon_int for APs */ u8 supported_rates[WLAN_SUPP_RATES_MAX]; @@ -95,9 +91,7 @@ struct sta_info { int vlan_id; -#ifdef CONFIG_IEEE80211N - struct ht_cap_ie ht_capabilities; /* IEEE 802.11n capabilities */ -#endif /* CONFIG_IEEE80211N */ + struct ieee80211_ht_capabilities *ht_capabilities; #ifdef CONFIG_IEEE80211W int sa_query_count; /* number of pending SA Query requests; @@ -113,14 +107,6 @@ struct sta_info { }; -/* Maximum number of AIDs to use for STAs; must be 2007 or lower - * (8802.11 limitation) */ -#define MAX_AID_TABLE_SIZE 128 - -#define STA_HASH_SIZE 256 -#define STA_HASH(sta) (sta[5]) - - /* Default value for maximum station inactivity. After AP_MAX_INACTIVITY has * passed since last received frame from the station, a nullfunc data frame is * sent to the station. If this frame is not acknowledged and no other frames @@ -136,4 +122,34 @@ struct sta_info { /* Number of seconds to keep STA entry after it has been deauthenticated. */ #define AP_MAX_INACTIVITY_AFTER_DEAUTH (1 * 5) -#endif /* AP_H */ + +struct hostapd_data; + +int ap_for_each_sta(struct hostapd_data *hapd, + int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, + void *ctx), + void *ctx); +struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta); +void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta); +void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta); +void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta); +void hostapd_free_stas(struct hostapd_data *hapd); +void ap_handle_timer(void *eloop_ctx, void *timeout_ctx); +void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta, + u32 session_timeout); +void ap_sta_no_session_timeout(struct hostapd_data *hapd, + struct sta_info *sta); +struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr); +void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, + u16 reason); +void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, + u16 reason); +int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, + int old_vlanid); +void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta); +void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta); +int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta); +void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *addr, u16 reason); + +#endif /* STA_INFO_H */ diff --git a/contrib/wpa/src/ap/tkip_countermeasures.c b/contrib/wpa/src/ap/tkip_countermeasures.c new file mode 100644 index 000000000000..9690348e9ccf --- /dev/null +++ b/contrib/wpa/src/ap/tkip_countermeasures.c @@ -0,0 +1,93 @@ +/* + * hostapd / TKIP countermeasures + * Copyright (c) 2002-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "hostapd.h" +#include "sta_info.h" +#include "ap_mlme.h" +#include "wpa_auth.h" +#include "tkip_countermeasures.h" + + +static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx, + void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + hapd->tkip_countermeasures = 0; + hapd->drv.set_countermeasures(hapd, 0); + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended"); +} + + +static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd) +{ + struct sta_info *sta; + + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated"); + + wpa_auth_countermeasures_start(hapd->wpa_auth); + hapd->tkip_countermeasures = 1; + hapd->drv.set_countermeasures(hapd, 1); + wpa_gtk_rekey(hapd->wpa_auth); + eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL); + eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop, + hapd, NULL); + for (sta = hapd->sta_list; sta != NULL; sta = sta->next) { + hapd->drv.sta_deauth(hapd, sta->addr, + WLAN_REASON_MICHAEL_MIC_FAILURE); + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | + WLAN_STA_AUTHORIZED); + hapd->drv.sta_remove(hapd, sta->addr); + } +} + + +void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local) +{ + time_t now; + + if (addr && local) { + struct sta_info *sta = ap_get_sta(hapd, addr); + if (sta != NULL) { + wpa_auth_sta_local_mic_failure_report(sta->wpa_sm); + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Michael MIC failure detected in " + "received frame"); + mlme_michaelmicfailure_indication(hapd, addr); + } else { + wpa_printf(MSG_DEBUG, + "MLME-MICHAELMICFAILURE.indication " + "for not associated STA (" MACSTR + ") ignored", MAC2STR(addr)); + return; + } + } + + time(&now); + if (now > hapd->michael_mic_failure + 60) { + hapd->michael_mic_failures = 1; + } else { + hapd->michael_mic_failures++; + if (hapd->michael_mic_failures > 1) + ieee80211_tkip_countermeasures_start(hapd); + } + hapd->michael_mic_failure = now; +} diff --git a/contrib/wpa/src/ap/tkip_countermeasures.h b/contrib/wpa/src/ap/tkip_countermeasures.h new file mode 100644 index 000000000000..5a1afceb0314 --- /dev/null +++ b/contrib/wpa/src/ap/tkip_countermeasures.h @@ -0,0 +1,20 @@ +/* + * hostapd / TKIP countermeasures + * Copyright (c) 2002-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef TKIP_COUNTERMEASURES_H +#define TKIP_COUNTERMEASURES_H + +void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local); + +#endif /* TKIP_COUNTERMEASURES_H */ diff --git a/contrib/wpa/src/ap/utils.c b/contrib/wpa/src/ap/utils.c new file mode 100644 index 000000000000..0ff48aeb37de --- /dev/null +++ b/contrib/wpa/src/ap/utils.c @@ -0,0 +1,88 @@ +/* + * AP mode helper functions + * Copyright (c) 2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "common/ieee802_11_defs.h" +#include "sta_info.h" +#include "hostapd.h" + + +int hostapd_register_probereq_cb(struct hostapd_data *hapd, + int (*cb)(void *ctx, const u8 *sa, + const u8 *ie, size_t ie_len), + void *ctx) +{ + struct hostapd_probereq_cb *n; + + n = os_realloc(hapd->probereq_cb, (hapd->num_probereq_cb + 1) * + sizeof(struct hostapd_probereq_cb)); + if (n == NULL) + return -1; + + hapd->probereq_cb = n; + n = &hapd->probereq_cb[hapd->num_probereq_cb]; + hapd->num_probereq_cb++; + + n->cb = cb; + n->ctx = ctx; + + return 0; +} + + +struct prune_data { + struct hostapd_data *hapd; + const u8 *addr; +}; + +static int prune_associations(struct hostapd_iface *iface, void *ctx) +{ + struct prune_data *data = ctx; + struct sta_info *osta; + struct hostapd_data *ohapd; + size_t j; + + for (j = 0; j < iface->num_bss; j++) { + ohapd = iface->bss[j]; + if (ohapd == data->hapd) + continue; + osta = ap_get_sta(ohapd, data->addr); + if (!osta) + continue; + + ap_sta_disassociate(ohapd, osta, WLAN_REASON_UNSPECIFIED); + } + + return 0; +} + +/** + * hostapd_prune_associations - Remove extraneous associations + * @hapd: Pointer to BSS data for the most recent association + * @addr: Associated STA address + * + * This function looks through all radios and BSS's for previous + * (stale) associations of STA. If any are found they are removed. + */ +void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr) +{ + struct prune_data data; + data.hapd = hapd; + data.addr = addr; + if (hapd->iface->for_each_interface) + hapd->iface->for_each_interface(hapd->iface->interfaces, + prune_associations, &data); +} diff --git a/contrib/wpa/hostapd/vlan_init.c b/contrib/wpa/src/ap/vlan_init.c similarity index 68% rename from contrib/wpa/hostapd/vlan_init.c rename to contrib/wpa/src/ap/vlan_init.c index 87c61e2c0115..c9d166a8f346 100644 --- a/contrib/wpa/hostapd/vlan_init.c +++ b/contrib/wpa/src/ap/vlan_init.c @@ -2,6 +2,7 @@ * hostapd / VLAN initialization * Copyright 2003, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. + * Copyright (c) 2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,10 +14,11 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" +#include "utils/common.h" #include "hostapd.h" -#include "driver.h" +#include "ap_config.h" #include "vlan_init.h" @@ -28,8 +30,8 @@ #include #include -#include "priv_netlink.h" -#include "eloop.h" +#include "drivers/priv_netlink.h" +#include "utils/eloop.h" struct full_dynamic_vlan { @@ -43,7 +45,8 @@ static int ifconfig_helper(const char *if_name, int up) struct ifreq ifr; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); + wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " + "failed: %s", __func__, strerror(errno)); return -1; } @@ -51,7 +54,9 @@ static int ifconfig_helper(const char *if_name, int up) os_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ); if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCGIFFLAGS]"); + wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCGIFFLAGS) failed " + "for interface %s: %s", + __func__, if_name, strerror(errno)); close(fd); return -1; } @@ -62,7 +67,9 @@ static int ifconfig_helper(const char *if_name, int up) ifr.ifr_flags &= ~IFF_UP; if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) { - perror("ioctl[SIOCSIFFLAGS]"); + wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCSIFFLAGS) failed " + "for interface %s (up=%d): %s", + __func__, if_name, up, strerror(errno)); close(fd); return -1; } @@ -74,12 +81,14 @@ static int ifconfig_helper(const char *if_name, int up) static int ifconfig_up(const char *if_name) { + wpa_printf(MSG_DEBUG, "VLAN: Set interface %s up", if_name); return ifconfig_helper(if_name, 1); } static int ifconfig_down(const char *if_name) { + wpa_printf(MSG_DEBUG, "VLAN: Set interface %s down", if_name); return ifconfig_helper(if_name, 0); } @@ -104,16 +113,19 @@ static int br_delif(const char *br_name, const char *if_name) unsigned long args[2]; int if_index; + wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); + wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " + "failed: %s", __func__, strerror(errno)); return -1; } if_index = if_nametoindex(if_name); if (if_index == 0) { - printf("Failure determining interface index for '%s'\n", - if_name); + wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining " + "interface index for '%s'", + __func__, if_name); close(fd); return -1; } @@ -126,7 +138,9 @@ static int br_delif(const char *br_name, const char *if_name) if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) { /* No error if interface already removed. */ - perror("ioctl[SIOCDEVPRIVATE,BRCTL_DEL_IF]"); + wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE," + "BRCTL_DEL_IF] failed for br_name=%s if_name=%s: " + "%s", __func__, br_name, if_name, strerror(errno)); close(fd); return -1; } @@ -150,16 +164,19 @@ static int br_addif(const char *br_name, const char *if_name) unsigned long args[2]; int if_index; + wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); + wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " + "failed: %s", __func__, strerror(errno)); return -1; } if_index = if_nametoindex(if_name); if (if_index == 0) { - printf("Failure determining interface index for '%s'\n", - if_name); + wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining " + "interface index for '%s'", + __func__, if_name); close(fd); return -1; } @@ -177,7 +194,9 @@ static int br_addif(const char *br_name, const char *if_name) return 1; } - perror("ioctl[SIOCDEVPRIVATE,BRCTL_ADD_IF]"); + wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE," + "BRCTL_ADD_IF] failed for br_name=%s if_name=%s: " + "%s", __func__, br_name, if_name, strerror(errno)); close(fd); return -1; } @@ -192,8 +211,10 @@ static int br_delbr(const char *br_name) int fd; unsigned long arg[2]; + wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); + wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " + "failed: %s", __func__, strerror(errno)); return -1; } @@ -202,7 +223,8 @@ static int br_delbr(const char *br_name) if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) { /* No error if bridge already removed. */ - perror("ioctl[BRCTL_DEL_BRIDGE]"); + wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_DEL_BRIDGE failed for " + "%s: %s", __func__, br_name, strerror(errno)); close(fd); return -1; } @@ -222,10 +244,13 @@ static int br_delbr(const char *br_name) static int br_addbr(const char *br_name) { int fd; - unsigned long arg[2]; + unsigned long arg[4]; + struct ifreq ifr; + wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); + wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " + "failed: %s", __func__, strerror(errno)); return -1; } @@ -238,12 +263,29 @@ static int br_addbr(const char *br_name) close(fd); return 1; } else { - perror("ioctl[BRCTL_ADD_BRIDGE]"); + wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_ADD_BRIDGE " + "failed for %s: %s", + __func__, br_name, strerror(errno)); close(fd); return -1; } } + /* Decrease forwarding delay to avoid EAPOL timeouts. */ + os_memset(&ifr, 0, sizeof(ifr)); + os_strlcpy(ifr.ifr_name, br_name, IFNAMSIZ); + arg[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY; + arg[1] = 1; + arg[2] = 0; + arg[3] = 0; + ifr.ifr_data = (char *) &arg; + if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { + wpa_printf(MSG_ERROR, "VLAN: %s: " + "BRCTL_SET_BRIDGE_FORWARD_DELAY (1 sec) failed for " + "%s: %s", __func__, br_name, strerror(errno)); + /* Continue anyway */ + } + close(fd); return 0; } @@ -259,7 +301,8 @@ static int br_getnumports(const char *br_name) struct ifreq ifr; if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); + wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " + "failed: %s", __func__, strerror(errno)); return -1; } @@ -273,7 +316,9 @@ static int br_getnumports(const char *br_name) ifr.ifr_data = (__caddr_t) arg; if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { - perror("ioctl[SIOCDEVPRIVATE,BRCTL_GET_PORT_LIST]"); + wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_GET_PORT_LIST " + "failed for %s: %s", + __func__, br_name, strerror(errno)); close(fd); return -1; } @@ -294,13 +339,16 @@ static int vlan_rem(const char *if_name) int fd; struct vlan_ioctl_args if_request; + wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name); if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) { - fprintf(stderr, "Interface name to long.\n"); + wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", + if_name); return -1; } if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); + wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " + "failed: %s", __func__, strerror(errno)); return -1; } @@ -310,7 +358,8 @@ static int vlan_rem(const char *if_name) if_request.cmd = DEL_VLAN_CMD; if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { - perror("ioctl[SIOCSIFVLAN,DEL_VLAN_CMD]"); + wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: " + "%s", __func__, if_name, strerror(errno)); close(fd); return -1; } @@ -333,15 +382,19 @@ static int vlan_add(const char *if_name, int vid) int fd; struct vlan_ioctl_args if_request; + wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)", + if_name, vid); ifconfig_up(if_name); if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) { - fprintf(stderr, "Interface name to long.\n"); + wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", + if_name); return -1; } if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); + wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " + "failed: %s", __func__, strerror(errno)); return -1; } @@ -363,6 +416,9 @@ static int vlan_add(const char *if_name, int vid) os_strncmp(if_request.u.device2, if_name, sizeof(if_request.u.device2)) == 0) { close(fd); + wpa_printf(MSG_DEBUG, "VLAN: vlan_add: " + "if_name %s exists already", + if_request.device1); return 1; } } @@ -376,7 +432,9 @@ static int vlan_add(const char *if_name, int vid) if_request.cmd = ADD_VLAN_CMD; if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { - perror("ioctl[SIOCSIFVLAN,ADD_VLAN_CMD]"); + wpa_printf(MSG_ERROR, "VLAN: %s: ADD_VLAN_CMD failed for %s: " + "%s", + __func__, if_request.device1, strerror(errno)); close(fd); return -1; } @@ -391,8 +449,11 @@ static int vlan_set_name_type(unsigned int name_type) int fd; struct vlan_ioctl_args if_request; + wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)", + name_type); if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("socket[AF_INET,SOCK_STREAM]"); + wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " + "failed: %s", __func__, strerror(errno)); return -1; } @@ -401,7 +462,9 @@ static int vlan_set_name_type(unsigned int name_type) if_request.u.name_type = name_type; if_request.cmd = SET_VLAN_NAME_TYPE_CMD; if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { - perror("ioctl[SIOCSIFVLAN,SET_VLAN_NAME_TYPE_CMD]"); + wpa_printf(MSG_ERROR, "VLAN: %s: SET_VLAN_NAME_TYPE_CMD " + "name_type=%u failed: %s", + __func__, name_type, strerror(errno)); close(fd); return -1; } @@ -418,6 +481,8 @@ static void vlan_newlink(char *ifname, struct hostapd_data *hapd) struct hostapd_vlan *vlan = hapd->conf->vlan; char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; + wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname); + while (vlan) { if (os_strcmp(ifname, vlan->ifname) == 0) { @@ -461,7 +526,8 @@ static void vlan_dellink(char *ifname, struct hostapd_data *hapd) char br_name[IFNAMSIZ]; struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan; char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; - int numports; + + wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname); first = prev = vlan; @@ -470,19 +536,24 @@ static void vlan_dellink(char *ifname, struct hostapd_data *hapd) os_snprintf(br_name, sizeof(br_name), "brvlan%d", vlan->vlan_id); + if (vlan->clean & DVLAN_CLEAN_WLAN_PORT) + br_delif(br_name, vlan->ifname); + if (tagged_interface) { os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", vlan->vlan_id); - - numports = br_getnumports(br_name); - if (numports == 1) { + if (vlan->clean & DVLAN_CLEAN_VLAN_PORT) br_delif(br_name, vlan_ifname); + ifconfig_down(vlan_ifname); + if (vlan->clean & DVLAN_CLEAN_VLAN) vlan_rem(vlan_ifname); + } - ifconfig_down(br_name); - br_delbr(br_name); - } + if ((vlan->clean & DVLAN_CLEAN_BR) && + br_getnumports(br_name) == 0) { + ifconfig_down(br_name); + br_delbr(br_name); } if (vlan == first) { @@ -561,7 +632,8 @@ static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx) (struct sockaddr *) &from, &fromlen); if (left < 0) { if (errno != EINTR && errno != EAGAIN) - perror("recvfrom(netlink)"); + wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s", + __func__, strerror(errno)); return; } @@ -572,8 +644,9 @@ static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx) len = h->nlmsg_len; plen = len - sizeof(*h); if (len > left || plen < 0) { - printf("Malformed netlink message: " - "len=%d left=%d plen=%d", len, left, plen); + wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink " + "message: len=%d left=%d plen=%d", + len, left, plen); break; } @@ -592,8 +665,8 @@ static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx) } if (left > 0) { - printf("%d extra bytes in the end of netlink message", - left); + wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of " + "netlink message", __func__, left); } } @@ -612,7 +685,9 @@ full_dynamic_vlan_init(struct hostapd_data *hapd) priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); if (priv->s < 0) { - perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)"); + wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW," + "NETLINK_ROUTE) failed: %s", + __func__, strerror(errno)); os_free(priv); return NULL; } @@ -621,7 +696,8 @@ full_dynamic_vlan_init(struct hostapd_data *hapd) local.nl_family = AF_NETLINK; local.nl_groups = RTMGRP_LINK; if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) { - perror("bind(netlink)"); + wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s", + __func__, strerror(errno)); close(priv->s); os_free(priv); return NULL; @@ -661,12 +737,11 @@ int vlan_setup_encryption_dyn(struct hostapd_data *hapd, * functions for setting up dynamic broadcast keys. */ for (i = 0; i < 4; i++) { if (mssid->wep.key[i] && - hostapd_set_encryption(dyn_vlan, hapd, "WEP", NULL, - i, mssid->wep.key[i], - mssid->wep.len[i], - i == mssid->wep.idx)) { - printf("VLAN: Could not set WEP encryption for " - "dynamic VLAN.\n"); + hapd->drv.set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i, + i == mssid->wep.idx, NULL, 0, + mssid->wep.key[i], mssid->wep.len[i])) { + wpa_printf(MSG_ERROR, "VLAN: Could not set WEP " + "encryption for dynamic VLAN"); return -1; } } @@ -679,14 +754,19 @@ static int vlan_dynamic_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan) { while (vlan) { - if (vlan->vlan_id != VLAN_ID_WILDCARD && - hostapd_if_add(hapd, HOSTAPD_IF_VLAN, vlan->ifname, NULL)) - { - if (errno != EEXIST) { - printf("Could not add VLAN iface: %s: %s\n", - vlan->ifname, strerror(errno)); - return -1; + if (vlan->vlan_id != VLAN_ID_WILDCARD) { + if (hapd->drv.vlan_if_add(hapd, vlan->ifname)) { + if (errno != EEXIST) { + wpa_printf(MSG_ERROR, "VLAN: Could " + "not add VLAN %s: %s", + vlan->ifname, + strerror(errno)); + return -1; + } } +#ifdef CONFIG_FULL_DYNAMIC_VLAN + ifconfig_up(vlan->ifname); +#endif /* CONFIG_FULL_DYNAMIC_VLAN */ } vlan = vlan->next; @@ -705,10 +785,10 @@ static void vlan_dynamic_remove(struct hostapd_data *hapd, next = vlan->next; if (vlan->vlan_id != VLAN_ID_WILDCARD && - hostapd_if_remove(hapd, HOSTAPD_IF_VLAN, vlan->ifname, - NULL)) { - printf("Could not remove VLAN iface: %s: %s\n", - vlan->ifname, strerror(errno)); + hapd->drv.vlan_if_remove(hapd, vlan->ifname)) { + wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN " + "iface: %s: %s", + vlan->ifname, strerror(errno)); } #ifdef CONFIG_FULL_DYNAMIC_VLAN if (vlan->clean) @@ -722,13 +802,13 @@ static void vlan_dynamic_remove(struct hostapd_data *hapd, int vlan_init(struct hostapd_data *hapd) { - if (vlan_dynamic_add(hapd, hapd->conf->vlan)) - return -1; - #ifdef CONFIG_FULL_DYNAMIC_VLAN hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd); #endif /* CONFIG_FULL_DYNAMIC_VLAN */ + if (vlan_dynamic_add(hapd, hapd->conf->vlan)) + return -1; + return 0; } @@ -743,17 +823,6 @@ void vlan_deinit(struct hostapd_data *hapd) } -int vlan_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss) -{ - vlan_dynamic_remove(hapd, oldbss->vlan); - if (vlan_dynamic_add(hapd, hapd->conf->vlan)) - return -1; - - return 0; -} - - struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, struct hostapd_vlan *vlan, int vlan_id) @@ -765,6 +834,8 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, vlan->vlan_id != VLAN_ID_WILDCARD) return NULL; + wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)", + __func__, vlan_id, vlan->ifname); ifname = os_strdup(vlan->ifname); if (ifname == NULL) return NULL; @@ -788,7 +859,7 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, pos); os_free(ifname); - if (hostapd_if_add(hapd, HOSTAPD_IF_VLAN, n->ifname, NULL)) { + if (hapd->drv.vlan_if_add(hapd, n->ifname)) { os_free(n); return NULL; } @@ -796,6 +867,10 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, n->next = hapd->conf->vlan; hapd->conf->vlan = n; +#ifdef CONFIG_FULL_DYNAMIC_VLAN + ifconfig_up(n->ifname); +#endif /* CONFIG_FULL_DYNAMIC_VLAN */ + return n; } @@ -807,6 +882,8 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id) if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID) return 1; + wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d)", __func__, vlan_id); + vlan = hapd->conf->vlan; while (vlan) { if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) { @@ -820,7 +897,7 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id) return 1; if (vlan->dynamic_vlan == 0) - hostapd_if_remove(hapd, HOSTAPD_IF_VLAN, vlan->ifname, NULL); + hapd->drv.vlan_if_remove(hapd, vlan->ifname); return 0; } diff --git a/contrib/wpa/hostapd/vlan_init.h b/contrib/wpa/src/ap/vlan_init.h similarity index 59% rename from contrib/wpa/hostapd/vlan_init.h rename to contrib/wpa/src/ap/vlan_init.h index cf55ac246220..382d5dee4f80 100644 --- a/contrib/wpa/hostapd/vlan_init.h +++ b/contrib/wpa/src/ap/vlan_init.h @@ -16,10 +16,9 @@ #ifndef VLAN_INIT_H #define VLAN_INIT_H +#ifndef CONFIG_NO_VLAN int vlan_init(struct hostapd_data *hapd); void vlan_deinit(struct hostapd_data *hapd); -int vlan_reconfig(struct hostapd_data *hapd, struct hostapd_config *oldconf, - struct hostapd_bss_config *oldbss); struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, struct hostapd_vlan *vlan, int vlan_id); @@ -27,5 +26,34 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id); int vlan_setup_encryption_dyn(struct hostapd_data *hapd, struct hostapd_ssid *mssid, const char *dyn_vlan); +#else /* CONFIG_NO_VLAN */ +static inline int vlan_init(struct hostapd_data *hapd) +{ + return 0; +} + +static inline void vlan_deinit(struct hostapd_data *hapd) +{ +} + +static inline struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, + struct hostapd_vlan *vlan, + int vlan_id) +{ + return NULL; +} + +static inline int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id) +{ + return -1; +} + +static inline int vlan_setup_encryption_dyn(struct hostapd_data *hapd, + struct hostapd_ssid *mssid, + const char *dyn_vlan) +{ + return -1; +} +#endif /* CONFIG_NO_VLAN */ #endif /* VLAN_INIT_H */ diff --git a/contrib/wpa/hostapd/wme.c b/contrib/wpa/src/ap/wmm.c similarity index 86% rename from contrib/wpa/hostapd/wme.c rename to contrib/wpa/src/ap/wmm.c index f2bbbd9cc2d0..36681309c3dc 100644 --- a/contrib/wpa/hostapd/wme.c +++ b/contrib/wpa/src/ap/wmm.c @@ -2,6 +2,7 @@ * hostapd / WMM (Wi-Fi Multimedia) * Copyright 2002-2003, Instant802 Networks, Inc. * Copyright 2005-2006, Devicescape Software, Inc. + * Copyright (c) 2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -13,13 +14,16 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" #include "hostapd.h" #include "ieee802_11.h" -#include "wme.h" #include "sta_info.h" -#include "driver.h" +#include "ap_config.h" +#include "wmm.h" /* TODO: maintain separate sequence and fragment numbers for each AC @@ -67,6 +71,9 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid) wmm->version = WMM_VERSION; wmm->qos_info = hapd->parameter_set_count & 0xf; + if (hapd->conf->wmm_uapsd) + wmm->qos_info |= 0x80; + /* fill in a parameter set record for each AC */ for (e = 0; e < 4; e++) { struct wmm_ac_parameter *ac = &wmm->ac[e]; @@ -90,7 +97,7 @@ u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid) /* This function is called when a station sends an association request with * WMM info element. The function returns zero on success or non-zero on any * error in WMM element. eid does not include Element ID and Length octets. */ -int hostapd_eid_wmm_valid(struct hostapd_data *hapd, u8 *eid, size_t len) +int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len) { struct wmm_information_element *wmm; @@ -117,23 +124,6 @@ int hostapd_eid_wmm_valid(struct hostapd_data *hapd, u8 *eid, size_t len) } -/* This function is called when a station sends an ACK frame for an AssocResp - * frame (status=success) and the matching AssocReq contained a WMM element. - */ -int hostapd_wmm_sta_config(struct hostapd_data *hapd, struct sta_info *sta) -{ - /* update kernel STA data for WMM related items (WLAN_STA_WPA flag) */ - if (sta->flags & WLAN_STA_WMM) - hostapd_sta_set_flags(hapd, sta->addr, sta->flags, - WLAN_STA_WMM, ~0); - else - hostapd_sta_set_flags(hapd, sta->addr, sta->flags, - 0, ~WLAN_STA_WMM); - - return 0; -} - - static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr, const struct wmm_tspec_element *tspec, u8 action_code, u8 dialogue_token, u8 status_code) @@ -160,30 +150,17 @@ static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr, os_memcpy(t, tspec, sizeof(struct wmm_tspec_element)); len = ((u8 *) (t + 1)) - buf; - if (hostapd_send_mgmt_frame(hapd, m, len, 0) < 0) + if (hapd->drv.send_mgmt_frame(hapd, m, len) < 0) perror("wmm_send_action: send"); } -static void wmm_addts_req(struct hostapd_data *hapd, - struct ieee80211_mgmt *mgmt, - struct wmm_tspec_element *tspec, size_t len) +int wmm_process_tspec(struct wmm_tspec_element *tspec) { - u8 *end = ((u8 *) mgmt) + len; int medium_time, pps, duration; int up, psb, dir, tid; u16 val, surplus; - if ((u8 *) (tspec + 1) > end) { - wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request"); - return; - } - - wpa_printf(MSG_DEBUG, "WMM: ADDTS Request (Dialog Token %d) for TSPEC " - "from " MACSTR, - mgmt->u.action.u.wmm_action.dialog_token, - MAC2STR(mgmt->sa)); - up = (tspec->ts_info[1] >> 3) & 0x07; psb = (tspec->ts_info[1] >> 2) & 0x01; dir = (tspec->ts_info[0] >> 5) & 0x03; @@ -204,7 +181,7 @@ static void wmm_addts_req(struct hostapd_data *hapd, val = le_to_host16(tspec->nominal_msdu_size); if (val == 0) { wpa_printf(MSG_DEBUG, "WMM: Invalid Nominal MSDU Size (0)"); - goto invalid; + return WMM_ADDTS_STATUS_INVALID_PARAMETERS; } /* pps = Ceiling((Mean Data Rate / 8) / Nominal MSDU Size) */ pps = ((le_to_host32(tspec->mean_data_rate) / 8) + val - 1) / val; @@ -213,7 +190,7 @@ static void wmm_addts_req(struct hostapd_data *hapd, if (le_to_host32(tspec->minimum_phy_rate) < 1000000) { wpa_printf(MSG_DEBUG, "WMM: Too small Minimum PHY Rate"); - goto invalid; + return WMM_ADDTS_STATUS_INVALID_PARAMETERS; } duration = (le_to_host16(tspec->nominal_msdu_size) & 0x7fff) * 8 / @@ -226,7 +203,7 @@ static void wmm_addts_req(struct hostapd_data *hapd, if (surplus <= 0x2000) { wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance not " "greater than unity"); - goto invalid; + return WMM_ADDTS_STATUS_INVALID_PARAMETERS; } medium_time = surplus * pps * duration / 0x2000; @@ -241,35 +218,47 @@ static void wmm_addts_req(struct hostapd_data *hapd, if (medium_time > 750000) { wpa_printf(MSG_DEBUG, "WMM: Refuse TSPEC request for over " "75%% of available bandwidth"); - wmm_send_action(hapd, mgmt->sa, tspec, - WMM_ACTION_CODE_ADDTS_RESP, - mgmt->u.action.u.wmm_action.dialog_token, - WMM_ADDTS_STATUS_REFUSED); - return; + return WMM_ADDTS_STATUS_REFUSED; } /* Convert to 32 microseconds per second unit */ tspec->medium_time = host_to_le16(medium_time / 32); - wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP, - mgmt->u.action.u.wmm_action.dialog_token, - WMM_ADDTS_STATUS_ADMISSION_ACCEPTED); - return; - -invalid: - wmm_send_action(hapd, mgmt->sa, tspec, - WMM_ACTION_CODE_ADDTS_RESP, - mgmt->u.action.u.wmm_action.dialog_token, - WMM_ADDTS_STATUS_INVALID_PARAMETERS); + return WMM_ADDTS_STATUS_ADMISSION_ACCEPTED; } -void hostapd_wmm_action(struct hostapd_data *hapd, struct ieee80211_mgmt *mgmt, - size_t len) +static void wmm_addts_req(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + struct wmm_tspec_element *tspec, size_t len) +{ + const u8 *end = ((const u8 *) mgmt) + len; + int res; + + if ((const u8 *) (tspec + 1) > end) { + wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request"); + return; + } + + wpa_printf(MSG_DEBUG, "WMM: ADDTS Request (Dialog Token %d) for TSPEC " + "from " MACSTR, + mgmt->u.action.u.wmm_action.dialog_token, + MAC2STR(mgmt->sa)); + + res = wmm_process_tspec(tspec); + wpa_printf(MSG_DEBUG, "WMM: ADDTS processing result: %d", res); + + wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP, + mgmt->u.action.u.wmm_action.dialog_token, res); +} + + +void hostapd_wmm_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len) { int action_code; int left = len - IEEE80211_HDRLEN - 4; - u8 *pos = ((u8 *) mgmt) + IEEE80211_HDRLEN + 4; + const u8 *pos = ((const u8 *) mgmt) + IEEE80211_HDRLEN + 4; struct ieee802_11_elems elems; struct sta_info *sta = ap_get_sta(hapd, mgmt->sa); diff --git a/contrib/wpa/src/ap/wmm.h b/contrib/wpa/src/ap/wmm.h new file mode 100644 index 000000000000..96b04e890963 --- /dev/null +++ b/contrib/wpa/src/ap/wmm.h @@ -0,0 +1,29 @@ +/* + * hostapd / WMM (Wi-Fi Multimedia) + * Copyright 2002-2003, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef WME_H +#define WME_H + +struct ieee80211_mgmt; +struct wmm_tspec_element; + +u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid); +int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, + size_t len); +void hostapd_wmm_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len); +int wmm_process_tspec(struct wmm_tspec_element *tspec); + +#endif /* WME_H */ diff --git a/contrib/wpa/hostapd/wpa.c b/contrib/wpa/src/ap/wpa_auth.c similarity index 89% rename from contrib/wpa/hostapd/wpa.c rename to contrib/wpa/src/ap/wpa_auth.c index 19b11d59d340..36cb0f4783c3 100644 --- a/contrib/wpa/hostapd/wpa.c +++ b/contrib/wpa/src/ap/wpa_auth.c @@ -12,23 +12,21 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" -#ifndef CONFIG_NATIVE_WINDOWS - -#include "common.h" -#include "config.h" -#include "eapol_sm.h" -#include "wpa.h" -#include "sha1.h" -#include "sha256.h" -#include "rc4.h" -#include "aes_wrap.h" -#include "crypto.h" -#include "eloop.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "utils/state_machine.h" +#include "common/ieee802_11_defs.h" +#include "crypto/aes_wrap.h" +#include "crypto/crypto.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "ap_config.h" #include "ieee802_11.h" -#include "pmksa_cache.h" -#include "state_machine.h" +#include "wpa_auth.h" +#include "pmksa_cache_auth.h" #include "wpa_auth_i.h" #include "wpa_auth_ie.h" @@ -38,7 +36,7 @@ static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx); -static void wpa_sm_step(struct wpa_state_machine *sm); +static int wpa_sm_step(struct wpa_state_machine *sm); static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len); static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx); static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, @@ -104,7 +102,7 @@ static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth, static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, int vlan_id, - const char *alg, const u8 *addr, int idx, + enum wpa_alg alg, const u8 *addr, int idx, u8 *key, size_t key_len) { if (wpa_auth->cb.set_key == NULL) @@ -123,15 +121,6 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, } -static inline int wpa_auth_get_seqnum_igtk(struct wpa_authenticator *wpa_auth, - const u8 *addr, int idx, u8 *seq) -{ - if (wpa_auth->cb.get_seqnum_igtk == NULL) - return -1; - return wpa_auth->cb.get_seqnum_igtk(wpa_auth->cb.ctx, addr, idx, seq); -} - - static inline int wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, const u8 *data, size_t data_len, int encrypt) @@ -382,7 +371,8 @@ struct wpa_authenticator * wpa_init(const u8 *addr, return NULL; } - wpa_auth->pmksa = pmksa_cache_init(wpa_auth_pmksa_free_cb, wpa_auth); + wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb, + wpa_auth); if (wpa_auth->pmksa == NULL) { wpa_printf(MSG_ERROR, "PMKSA cache initialization failed."); os_free(wpa_auth->wpa_ie); @@ -395,7 +385,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr, if (wpa_auth->ft_pmk_cache == NULL) { wpa_printf(MSG_ERROR, "FT PMK cache initialization failed."); os_free(wpa_auth->wpa_ie); - pmksa_cache_deinit(wpa_auth->pmksa); + pmksa_cache_auth_deinit(wpa_auth->pmksa); os_free(wpa_auth); return NULL; } @@ -431,7 +421,7 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth) wpa_stsl_remove(wpa_auth, wpa_auth->stsl_negotiations); #endif /* CONFIG_PEERKEY */ - pmksa_cache_deinit(wpa_auth->pmksa); + pmksa_cache_auth_deinit(wpa_auth->pmksa); #ifdef CONFIG_IEEE80211R wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache); @@ -501,26 +491,25 @@ wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr) } -void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm) +int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm) { if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) - return; + return -1; #ifdef CONFIG_IEEE80211R if (sm->ft_completed) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "FT authentication already completed - do not " "start 4-way handshake"); - return; + return 0; } #endif /* CONFIG_IEEE80211R */ if (sm->started) { os_memset(&sm->key_replay, 0, sizeof(sm->key_replay)); sm->ReAuthenticationRequest = TRUE; - wpa_sm_step(sm); - return; + return wpa_sm_step(sm); } wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, @@ -528,10 +517,11 @@ void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, sm->started = 1; sm->Init = TRUE; - wpa_sm_step(sm); + if (wpa_sm_step(sm) == 1) + return 1; /* should not really happen */ sm->Init = FALSE; sm->AuthenticationRequest = TRUE; - wpa_sm_step(sm); + return wpa_sm_step(sm); } @@ -549,6 +539,9 @@ void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm) static void wpa_free_sta_sm(struct wpa_state_machine *sm) { +#ifdef CONFIG_IEEE80211R + os_free(sm->assoc_resp_ftie); +#endif /* CONFIG_IEEE80211R */ os_free(sm->last_rx_eapol_key); os_free(sm->wpa_ie); os_free(sm); @@ -608,6 +601,56 @@ static int wpa_replay_counter_valid(struct wpa_state_machine *sm, } +#ifdef CONFIG_IEEE80211R +static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + struct wpa_eapol_ie_parse *kde) +{ + struct wpa_ie_data ie; + struct rsn_mdie *mdie; + + if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 || + ie.num_pmkid != 1 || ie.pmkid == NULL) { + wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in " + "FT 4-way handshake message 2/4"); + return -1; + } + + os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant", + sm->sup_pmk_r1_name, PMKID_LEN); + + if (!kde->mdie || !kde->ftie) { + wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake " + "message 2/4", kde->mdie ? "FTIE" : "MDIE"); + return -1; + } + + mdie = (struct rsn_mdie *) (kde->mdie + 2); + if (kde->mdie[1] < sizeof(struct rsn_mdie) || + os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain, + MOBILITY_DOMAIN_ID_LEN) != 0) { + wpa_printf(MSG_DEBUG, "FT: MDIE mismatch"); + return -1; + } + + if (sm->assoc_resp_ftie && + (kde->ftie[1] != sm->assoc_resp_ftie[1] || + os_memcmp(kde->ftie, sm->assoc_resp_ftie, + 2 + sm->assoc_resp_ftie[1]) != 0)) { + wpa_printf(MSG_DEBUG, "FT: FTIE mismatch"); + wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4", + kde->ftie, kde->ftie_len); + wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp", + sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]); + return -1; + } + + return 0; +} +#endif /* CONFIG_IEEE80211R */ + + void wpa_receive(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, u8 *data, size_t data_len) @@ -619,6 +662,9 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, SMK_M1, SMK_M3, SMK_ERROR } msg; char *msgtxt; struct wpa_eapol_ie_parse kde; + int ft; + const u8 *eapol_key_ie; + size_t eapol_key_ie_len; if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) return; @@ -749,9 +795,26 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, sm->wpa_ptk_state); return; } + if (wpa_parse_kde_ies((u8 *) (key + 1), key_data_length, + &kde) < 0) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key msg 2/4 with " + "invalid Key Data contents"); + return; + } + if (kde.rsn_ie) { + eapol_key_ie = kde.rsn_ie; + eapol_key_ie_len = kde.rsn_ie_len; + } else { + eapol_key_ie = kde.wpa_ie; + eapol_key_ie_len = kde.wpa_ie_len; + } + ft = sm->wpa == WPA_VERSION_WPA2 && + wpa_key_mgmt_ft(sm->wpa_key_mgmt); if (sm->wpa_ie == NULL || - sm->wpa_ie_len != key_data_length || - os_memcmp(sm->wpa_ie, key + 1, key_data_length) != 0) { + wpa_compare_rsn_ie(ft, + sm->wpa_ie, sm->wpa_ie_len, + eapol_key_ie, eapol_key_ie_len)) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, "WPA IE from (Re)AssocReq did not " "match with msg 2/4"); @@ -760,11 +823,17 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, sm->wpa_ie, sm->wpa_ie_len); } wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4", - (u8 *) (key + 1), key_data_length); + eapol_key_ie, eapol_key_ie_len); /* MLME-DEAUTHENTICATE.request */ wpa_sta_disconnect(wpa_auth, sm->addr); return; } +#ifdef CONFIG_IEEE80211R + if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) { + wpa_sta_disconnect(wpa_auth, sm->addr); + return; + } +#endif /* CONFIG_IEEE80211R */ break; case PAIRWISE_4: if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || @@ -1178,18 +1247,19 @@ void wpa_remove_ptk(struct wpa_state_machine *sm) { sm->PTK_valid = FALSE; os_memset(&sm->PTK, 0, sizeof(sm->PTK)); - wpa_auth_set_key(sm->wpa_auth, 0, "none", sm->addr, 0, (u8 *) "", 0); + wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, (u8 *) "", + 0); sm->pairwise_set = FALSE; eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); } -void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event) +int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event) { int remove_ptk = 1; if (sm == NULL) - return; + return -1; wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "event %d notification", event); @@ -1204,6 +1274,24 @@ void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event) break; case WPA_REAUTH: case WPA_REAUTH_EAPOL: + if (!sm->started) { + /* + * When using WPS, we may end up here if the STA + * manages to re-associate without the previous STA + * entry getting removed. Consequently, we need to make + * sure that the WPA state machines gets initialized + * properly at this point. + */ + wpa_printf(MSG_DEBUG, "WPA state machine had not been " + "started - initialize now"); + sm->started = 1; + sm->Init = TRUE; + if (wpa_sm_step(sm) == 1) + return 1; /* should not really happen */ + sm->Init = FALSE; + sm->AuthenticationRequest = TRUE; + break; + } if (sm->GUpdateStationKeys) { /* * Reauthentication cancels the pending group key @@ -1217,9 +1305,13 @@ void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event) break; case WPA_ASSOC_FT: #ifdef CONFIG_IEEE80211R + wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration " + "after association"); + wpa_ft_install_ptk(sm); + /* Using FT protocol, not WPA auth state machine */ sm->ft_completed = 1; - return; + return 0; #else /* CONFIG_IEEE80211R */ break; #endif /* CONFIG_IEEE80211R */ @@ -1242,22 +1334,22 @@ void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event) wpa_remove_ptk(sm); } - wpa_sm_step(sm); + return wpa_sm_step(sm); } -static const char * wpa_alg_txt(int alg) +static enum wpa_alg wpa_alg_enum(int alg) { switch (alg) { case WPA_CIPHER_CCMP: - return "CCMP"; + return WPA_ALG_CCMP; case WPA_CIPHER_TKIP: - return "TKIP"; + return WPA_ALG_TKIP; case WPA_CIPHER_WEP104: case WPA_CIPHER_WEP40: - return "WEP"; + return WPA_ALG_WEP; default: - return ""; + return WPA_ALG_NONE; } } @@ -1492,6 +1584,27 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) return; } +#ifdef CONFIG_IEEE80211R + if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + /* + * Verify that PMKR1Name from EAPOL-Key message 2/4 matches + * with the value we derived. + */ + if (os_memcmp(sm->sup_pmk_r1_name, sm->pmk_r1_name, + WPA_PMK_NAME_LEN) != 0) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "PMKR1Name mismatch in FT 4-way " + "handshake"); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from " + "Supplicant", + sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", + sm->pmk_r1_name, WPA_PMK_NAME_LEN); + return; + } + } +#endif /* CONFIG_IEEE80211R */ + eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { @@ -1537,8 +1650,8 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) igtk.keyid[0] = gsm->GN_igtk; igtk.keyid[1] = 0; - if (wpa_auth_get_seqnum_igtk(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn) - < 0) + if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE || + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, igtk.pn) < 0) os_memset(igtk.pn, 0, sizeof(igtk.pn)); os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK, @@ -1581,10 +1694,12 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) return; } - /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, GTK[GN]) + /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], + GTK[GN], IGTK, [FTIE], [TIE * 2]) */ os_memset(rsc, 0, WPA_KEY_RSC_LEN); wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); + /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */ wpa_ie = sm->wpa_auth->wpa_ie; wpa_ie_len = sm->wpa_auth->wpa_ie_len; if (sm->wpa == WPA_VERSION_WPA && @@ -1616,6 +1731,12 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) kde_len = wpa_ie_len + ieee80211w_kde_len(sm); if (gtk) kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */ + kde_len += 300; /* FTIE + 2 * TIE */ + } +#endif /* CONFIG_IEEE80211R */ kde = os_malloc(kde_len); if (kde == NULL) return; @@ -1623,6 +1744,18 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) pos = kde; os_memcpy(pos, wpa_ie, wpa_ie_len); pos += wpa_ie_len; +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + int res = wpa_insert_pmkid(kde, pos - kde, sm->pmk_r1_name); + if (res < 0) { + wpa_printf(MSG_ERROR, "FT: Failed to insert " + "PMKR1Name into RSN IE in EAPOL-Key data"); + os_free(kde); + return; + } + pos += res; + } +#endif /* CONFIG_IEEE80211R */ if (gtk) { u8 hdr[2]; hdr[0] = keyidx & 0x03; @@ -1632,6 +1765,40 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) } pos = ieee80211w_kde_add(sm, pos); +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + int res; + struct wpa_auth_config *conf; + + conf = &sm->wpa_auth->conf; + res = wpa_write_ftie(conf, conf->r0_key_holder, + conf->r0_key_holder_len, + NULL, NULL, pos, kde + kde_len - pos, + NULL, 0); + if (res < 0) { + wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " + "into EAPOL-Key Key Data"); + os_free(kde); + return; + } + pos += res; + + /* TIE[ReassociationDeadline] (TU) */ + *pos++ = WLAN_EID_TIMEOUT_INTERVAL; + *pos++ = 5; + *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE; + WPA_PUT_LE32(pos, conf->reassociation_deadline); + pos += 4; + + /* TIE[KeyLifetime] (seconds) */ + *pos++ = WLAN_EID_TIMEOUT_INTERVAL; + *pos++ = 5; + *pos++ = WLAN_TIMEOUT_KEY_LIFETIME; + WPA_PUT_LE32(pos, conf->r0_key_lifetime * 60); + pos += 4; + } +#endif /* CONFIG_IEEE80211R */ + wpa_send_eapol(sm->wpa_auth, sm, (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | @@ -1646,13 +1813,13 @@ SM_STATE(WPA_PTK, PTKINITDONE) SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk); sm->EAPOLKeyReceived = FALSE; if (sm->Pair) { - char *alg; + enum wpa_alg alg; int klen; if (sm->pairwise == WPA_CIPHER_TKIP) { - alg = "TKIP"; + alg = WPA_ALG_TKIP; klen = 32; } else { - alg = "CCMP"; + alg = WPA_ALG_CCMP; klen = 16; } if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, @@ -1934,7 +2101,7 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, group->GTK[group->GN - 1], group->GTK_len); #ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w != WPA_NO_IEEE80211W) { + if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { if (os_get_random(group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN) < 0) { wpa_printf(MSG_INFO, "RSN: Failed to get new random " @@ -2032,13 +2199,13 @@ static void wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth, group->changed = TRUE; group->wpa_group_state = WPA_GROUP_SETKEYSDONE; wpa_auth_set_key(wpa_auth, group->vlan_id, - wpa_alg_txt(wpa_auth->conf.wpa_group), + wpa_alg_enum(wpa_auth->conf.wpa_group), NULL, group->GN, group->GTK[group->GN - 1], group->GTK_len); #ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w != WPA_NO_IEEE80211W) { - wpa_auth_set_key(wpa_auth, group->vlan_id, "IGTK", + if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { + wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK, NULL, group->GN_igtk, group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN); @@ -2067,17 +2234,17 @@ static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, } -static void wpa_sm_step(struct wpa_state_machine *sm) +static int wpa_sm_step(struct wpa_state_machine *sm) { if (sm == NULL) - return; + return 0; if (sm->in_step_loop) { /* This should not happen, but if it does, make sure we do not * end up freeing the state machine too early by exiting the * recursive call. */ wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively"); - return; + return 0; } sm->in_step_loop = 1; @@ -2102,7 +2269,9 @@ static void wpa_sm_step(struct wpa_state_machine *sm) wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state " "machine deinit for " MACSTR, MAC2STR(sm->addr)); wpa_free_sta_sm(sm); + return 1; } + return 0; } @@ -2404,9 +2573,9 @@ int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, if (sm == NULL || sm->wpa != WPA_VERSION_WPA2) return -1; - if (pmksa_cache_add(sm->wpa_auth->pmksa, pmk, PMK_LEN, - sm->wpa_auth->addr, sm->addr, session_timeout, - eapol, sm->wpa_key_mgmt)) + if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, PMK_LEN, + sm->wpa_auth->addr, sm->addr, session_timeout, + eapol, sm->wpa_key_mgmt)) return 0; return -1; @@ -2421,9 +2590,9 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, if (wpa_auth == NULL) return -1; - if (pmksa_cache_add(wpa_auth->pmksa, pmk, len, wpa_auth->addr, - sta_addr, session_timeout, eapol, - WPA_KEY_MGMT_IEEE8021X)) + if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, wpa_auth->addr, + sta_addr, session_timeout, eapol, + WPA_KEY_MGMT_IEEE8021X)) return 0; return -1; @@ -2480,5 +2649,3 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) sm->group = group; return 0; } - -#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/contrib/wpa/hostapd/wpa.h b/contrib/wpa/src/ap/wpa_auth.h similarity index 91% rename from contrib/wpa/hostapd/wpa.h rename to contrib/wpa/src/ap/wpa_auth.h index 7d9b3d310677..d0136c71b666 100644 --- a/contrib/wpa/hostapd/wpa.h +++ b/contrib/wpa/src/ap/wpa_auth.h @@ -15,8 +15,9 @@ #ifndef WPA_AUTH_H #define WPA_AUTH_H -#include "eapol_common.h" -#include "wpa_common.h" +#include "common/defs.h" +#include "common/eapol_common.h" +#include "common/wpa_common.h" #ifdef _MSC_VER #pragma pack(push, 1) @@ -44,13 +45,9 @@ struct ft_rrb_frame { #define FT_PACKET_R0KH_R1KH_RESP 201 #define FT_PACKET_R0KH_R1KH_PUSH 202 -#ifndef ETH_P_RRB -#define ETH_P_RRB 0x890D -#endif /* ETH_P_RRB */ - #define FT_R0KH_R1KH_PULL_DATA_LEN 44 #define FT_R0KH_R1KH_RESP_DATA_LEN 76 -#define FT_R0KH_R1KH_PUSH_DATA_LEN 80 +#define FT_R0KH_R1KH_PUSH_DATA_LEN 88 struct ft_r0kh_r1kh_pull_frame { u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ @@ -77,14 +74,15 @@ struct ft_r0kh_r1kh_resp_frame { u8 s1kh_id[ETH_ALEN]; /* copied from pull */ u8 pmk_r1[PMK_LEN]; u8 pmk_r1_name[WPA_PMK_NAME_LEN]; - u8 pad[4]; /* 8-octet boundary for AES key wrap */ + le16 pairwise; + u8 pad[2]; /* 8-octet boundary for AES key wrap */ u8 key_wrap_extra[8]; } STRUCT_PACKED; struct ft_r0kh_r1kh_push_frame { u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */ - le16 data_length; /* little endian length of data (80) */ + le16 data_length; /* little endian length of data (88) */ u8 ap_address[ETH_ALEN]; /* Encrypted with AES key-wrap */ @@ -95,6 +93,8 @@ struct ft_r0kh_r1kh_push_frame { u8 pmk_r0_name[WPA_PMK_NAME_LEN]; u8 pmk_r1[PMK_LEN]; u8 pmk_r1_name[WPA_PMK_NAME_LEN]; + le16 pairwise; + u8 pad[6]; /* 8-octet boundary for AES key wrap */ u8 key_wrap_extra[8]; } STRUCT_PACKED; @@ -142,13 +142,10 @@ struct wpa_auth_config { int eapol_version; int peerkey; int wmm_enabled; + int wmm_uapsd; int okc; #ifdef CONFIG_IEEE80211W - enum { - WPA_NO_IEEE80211W = 0, - WPA_IEEE80211W_OPTIONAL = 1, - WPA_IEEE80211W_REQUIRED = 2 - } ieee80211w; + enum mfp_options ieee80211w; #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_IEEE80211R #define SSID_LEN 32 @@ -187,10 +184,9 @@ struct wpa_auth_callbacks { int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var); const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *prev_psk); int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len); - int (*set_key)(void *ctx, int vlan_id, const char *alg, const u8 *addr, - int idx, u8 *key, size_t key_len); + int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg, + const u8 *addr, int idx, u8 *key, size_t key_len); int (*get_seqnum)(void *ctx, const u8 *addr, int idx, u8 *seq); - int (*get_seqnum_igtk)(void *ctx, const u8 *addr, int idx, u8 *seq); int (*send_eapol)(void *ctx, const u8 *addr, const u8 *data, size_t data_len, int encrypt); int (*for_each_sta)(void *ctx, int (*cb)(struct wpa_state_machine *sm, @@ -227,8 +223,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, int wpa_auth_uses_mfp(struct wpa_state_machine *sm); struct wpa_state_machine * wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr); -void wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm); +int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm); void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm); void wpa_auth_sta_deinit(struct wpa_state_machine *sm); void wpa_receive(struct wpa_authenticator *wpa_auth, @@ -239,7 +235,7 @@ typedef enum { WPA_REAUTH_EAPOL, WPA_ASSOC_FT } wpa_event; void wpa_remove_ptk(struct wpa_state_machine *sm); -void wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event); +int wpa_auth_sm_event(struct wpa_state_machine *sm, wpa_event event); void wpa_auth_sm_notify(struct wpa_state_machine *sm); void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth); int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen); @@ -266,7 +262,8 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id); #ifdef CONFIG_IEEE80211R u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, - size_t max_len, int auth_alg); + size_t max_len, int auth_alg, + const u8 *req_ies, size_t req_ies_len); void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, u16 auth_transaction, const u8 *ies, size_t ies_len, void (*cb)(void *ctx, const u8 *dst, const u8 *bssid, diff --git a/contrib/wpa/hostapd/wpa_ft.c b/contrib/wpa/src/ap/wpa_auth_ft.c similarity index 77% rename from contrib/wpa/hostapd/wpa_ft.c rename to contrib/wpa/src/ap/wpa_auth_ft.c index 31391051febd..c9871d9a61bf 100644 --- a/contrib/wpa/hostapd/wpa_ft.c +++ b/contrib/wpa/src/ap/wpa_auth_ft.c @@ -1,6 +1,6 @@ /* * hostapd - IEEE 802.11r - Fast BSS Transition - * Copyright (c) 2004-2007, Jouni Malinen + * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,25 +12,50 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" -#include "common.h" -#include "config.h" -#include "wpa.h" -#include "aes_wrap.h" +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "crypto/aes_wrap.h" +#include "ap_config.h" #include "ieee802_11.h" -#include "defs.h" +#include "wmm.h" +#include "wpa_auth.h" #include "wpa_auth_i.h" #include "wpa_auth_ie.h" #ifdef CONFIG_IEEE80211R +struct wpa_ft_ies { + const u8 *mdie; + size_t mdie_len; + const u8 *ftie; + size_t ftie_len; + const u8 *r1kh_id; + const u8 *gtk; + size_t gtk_len; + const u8 *r0kh_id; + size_t r0kh_id_len; + const u8 *rsn; + size_t rsn_len; + const u8 *rsn_pmkid; + const u8 *ric; + size_t ric_len; +}; + + +static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, + struct wpa_ft_ies *parse); + + static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst, const u8 *data, size_t data_len) { if (wpa_auth->cb.send_ether == NULL) return -1; + wpa_printf(MSG_DEBUG, "FT: RRB send to " MACSTR, MAC2STR(dst)); return wpa_auth->cb.send_ether(wpa_auth->cb.ctx, dst, ETH_P_RRB, data, data_len); } @@ -73,11 +98,11 @@ int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len) } -static int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, - size_t r0kh_id_len, - const u8 *anonce, const u8 *snonce, - u8 *buf, size_t len, const u8 *subelem, - size_t subelem_len) +int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, + size_t r0kh_id_len, + const u8 *anonce, const u8 *snonce, + u8 *buf, size_t len, const u8 *subelem, + size_t subelem_len) { u8 *pos = buf, *ielen; struct rsn_ftie *hdr; @@ -127,6 +152,7 @@ struct wpa_ft_pmk_r0_sa { u8 pmk_r0[PMK_LEN]; u8 pmk_r0_name[WPA_PMK_NAME_LEN]; u8 spa[ETH_ALEN]; + int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */ /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */ int pmk_r1_pushed; }; @@ -136,6 +162,7 @@ struct wpa_ft_pmk_r1_sa { u8 pmk_r1[PMK_LEN]; u8 pmk_r1_name[WPA_PMK_NAME_LEN]; u8 spa[ETH_ALEN]; + int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */ /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */ }; @@ -181,7 +208,7 @@ void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache) static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth, const u8 *spa, const u8 *pmk_r0, - const u8 *pmk_r0_name) + const u8 *pmk_r0_name, int pairwise) { struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; struct wpa_ft_pmk_r0_sa *r0; @@ -195,6 +222,7 @@ static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth, os_memcpy(r0->pmk_r0, pmk_r0, PMK_LEN); os_memcpy(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN); os_memcpy(r0->spa, spa, ETH_ALEN); + r0->pairwise = pairwise; r0->next = cache->pmk_r0; cache->pmk_r0 = r0; @@ -205,7 +233,7 @@ static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth, static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth, const u8 *spa, const u8 *pmk_r0_name, - u8 *pmk_r0) + u8 *pmk_r0, int *pairwise) { struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; struct wpa_ft_pmk_r0_sa *r0; @@ -216,6 +244,8 @@ static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth, os_memcmp(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN) == 0) { os_memcpy(pmk_r0, r0->pmk_r0, PMK_LEN); + if (pairwise) + *pairwise = r0->pairwise; return 0; } @@ -228,7 +258,7 @@ static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth, static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *spa, const u8 *pmk_r1, - const u8 *pmk_r1_name) + const u8 *pmk_r1_name, int pairwise) { struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; struct wpa_ft_pmk_r1_sa *r1; @@ -242,6 +272,7 @@ static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth, os_memcpy(r1->pmk_r1, pmk_r1, PMK_LEN); os_memcpy(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN); os_memcpy(r1->spa, spa, ETH_ALEN); + r1->pairwise = pairwise; r1->next = cache->pmk_r1; cache->pmk_r1 = r1; @@ -252,7 +283,7 @@ static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth, static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *spa, const u8 *pmk_r1_name, - u8 *pmk_r1) + u8 *pmk_r1, int *pairwise) { struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache; struct wpa_ft_pmk_r1_sa *r1; @@ -263,6 +294,8 @@ static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth, os_memcmp(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN) == 0) { os_memcpy(pmk_r1, r1->pmk_r1, PMK_LEN); + if (pairwise) + *pairwise = r1->pairwise; return 0; } @@ -324,7 +357,7 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, struct wpa_ptk *ptk, size_t ptk_len) { u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN]; - u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN]; + u8 pmk_r1[PMK_LEN]; u8 ptk_name[WPA_PMK_NAME_LEN]; const u8 *mdid = sm->wpa_auth->conf.mobility_domain; const u8 *r0kh = sm->wpa_auth->conf.r0_key_holder; @@ -344,16 +377,19 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, r0kh, r0kh_len, sm->addr, pmk_r0, pmk_r0_name); wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, PMK_LEN); wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN); - wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_name); + wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_name, + sm->pairwise); wpa_derive_pmk_r1(pmk_r0, pmk_r0_name, r1kh, sm->addr, - pmk_r1, pmk_r1_name); + pmk_r1, sm->pmk_r1_name); wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); - wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, pmk_r1_name); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name, + WPA_PMK_NAME_LEN); + wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, sm->pmk_r1_name, + sm->pairwise); wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, - sm->wpa_auth->addr, pmk_r1_name, + sm->wpa_auth->addr, sm->pmk_r1_name, (u8 *) ptk, ptk_len, ptk_name); wpa_hexdump_key(MSG_DEBUG, "FT: PTK", (u8 *) ptk, ptk_len); wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); @@ -371,17 +407,6 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, } -#ifdef CONFIG_IEEE80211W -static inline int wpa_auth_get_seqnum_igtk(struct wpa_authenticator *wpa_auth, - const u8 *addr, int idx, u8 *seq) -{ - if (wpa_auth->cb.get_seqnum_igtk == NULL) - return -1; - return wpa_auth->cb.get_seqnum_igtk(wpa_auth->cb.ctx, addr, idx, seq); -} -#endif /* CONFIG_IEEE80211W */ - - static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) { u8 *subelem; @@ -414,20 +439,21 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) key = gsm->GTK[gsm->GN - 1]; /* - * Sub-elem ID[1] | Length[1] | Key Info[1] | Key Length[1] | RSC[8] | + * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] | * Key[5..32]. */ - subelem_len = 12 + key_len + 8; + subelem_len = 13 + key_len + 8; subelem = os_zalloc(subelem_len); if (subelem == NULL) return NULL; subelem[0] = FTIE_SUBELEM_GTK; - subelem[1] = 10 + key_len + 8; - subelem[2] = gsm->GN & 0x03; /* Key ID in B0-B1 of Key Info */ - subelem[3] = gsm->GTK_len; - wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 4); - if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 12)) { + subelem[1] = 11 + key_len + 8; + /* Key ID in B0-B1 of Key Info */ + WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03); + subelem[4] = gsm->GTK_len; + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5); + if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 13)) { os_free(subelem); return NULL; } @@ -456,7 +482,7 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len) *pos++ = subelem_len - 2; WPA_PUT_LE16(pos, gsm->GN_igtk); pos += 2; - wpa_auth_get_seqnum_igtk(sm->wpa_auth, NULL, gsm->GN_igtk, pos); + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos); pos += 6; *pos++ = WPA_IGTK_LEN; if (aes_wrap(sm->PTK.kek, WPA_IGTK_LEN / 8, @@ -471,14 +497,125 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len) #endif /* CONFIG_IEEE80211W */ -u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, - size_t max_len, int auth_alg) +static u8 * wpa_ft_process_rdie(u8 *pos, u8 *end, u8 id, u8 descr_count, + const u8 *ies, size_t ies_len) { - u8 *end, *mdie, *ftie, *rsnie, *r0kh_id, *subelem = NULL; - size_t mdie_len, ftie_len, rsnie_len, r0kh_id_len, subelem_len = 0; + struct ieee802_11_elems parse; + struct rsn_rdie *rdie; + + wpa_printf(MSG_DEBUG, "FT: Resource Request: id=%d descr_count=%d", + id, descr_count); + wpa_hexdump(MSG_MSGDUMP, "FT: Resource descriptor IE(s)", + ies, ies_len); + + if (end - pos < (int) sizeof(*rdie)) { + wpa_printf(MSG_ERROR, "FT: Not enough room for response RDIE"); + return pos; + } + + *pos++ = WLAN_EID_RIC_DATA; + *pos++ = sizeof(*rdie); + rdie = (struct rsn_rdie *) pos; + rdie->id = id; + rdie->descr_count = 0; + rdie->status_code = host_to_le16(WLAN_STATUS_SUCCESS); + pos += sizeof(*rdie); + + if (ieee802_11_parse_elems((u8 *) ies, ies_len, &parse, 1) == + ParseFailed) { + wpa_printf(MSG_DEBUG, "FT: Failed to parse request IEs"); + rdie->status_code = + host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE); + return pos; + } + +#ifdef NEED_AP_MLME + if (parse.wmm_tspec) { + struct wmm_tspec_element *tspec; + int res; + + if (parse.wmm_tspec_len + 2 < (int) sizeof(*tspec)) { + wpa_printf(MSG_DEBUG, "FT: Too short WMM TSPEC IE " + "(%d)", (int) parse.wmm_tspec_len); + rdie->status_code = + host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE); + return pos; + } + if (end - pos < (int) sizeof(*tspec)) { + wpa_printf(MSG_ERROR, "FT: Not enough room for " + "response TSPEC"); + rdie->status_code = + host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE); + return pos; + } + tspec = (struct wmm_tspec_element *) pos; + os_memcpy(tspec, parse.wmm_tspec - 2, sizeof(*tspec)); + res = wmm_process_tspec(tspec); + wpa_printf(MSG_DEBUG, "FT: ADDTS processing result: %d", res); + if (res == WMM_ADDTS_STATUS_INVALID_PARAMETERS) + rdie->status_code = + host_to_le16(WLAN_STATUS_INVALID_PARAMETERS); + else if (res == WMM_ADDTS_STATUS_REFUSED) + rdie->status_code = + host_to_le16(WLAN_STATUS_REQUEST_DECLINED); + else { + /* TSPEC accepted; include updated TSPEC in response */ + rdie->descr_count = 1; + pos += sizeof(*tspec); + } + return pos; + } +#endif /* NEED_AP_MLME */ + + wpa_printf(MSG_DEBUG, "FT: No supported resource requested"); + rdie->status_code = host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE); + return pos; +} + + +static u8 * wpa_ft_process_ric(u8 *pos, u8 *end, const u8 *ric, size_t ric_len) +{ + const u8 *rpos, *start; + const struct rsn_rdie *rdie; + + wpa_hexdump(MSG_MSGDUMP, "FT: RIC Request", ric, ric_len); + + rpos = ric; + while (rpos + sizeof(*rdie) < ric + ric_len) { + if (rpos[0] != WLAN_EID_RIC_DATA || rpos[1] < sizeof(*rdie) || + rpos + 2 + rpos[1] > ric + ric_len) + break; + rdie = (const struct rsn_rdie *) (rpos + 2); + rpos += 2 + rpos[1]; + start = rpos; + + while (rpos + 2 <= ric + ric_len && + rpos + 2 + rpos[1] <= ric + ric_len) { + if (rpos[0] == WLAN_EID_RIC_DATA) + break; + rpos += 2 + rpos[1]; + } + pos = wpa_ft_process_rdie(pos, end, rdie->id, + rdie->descr_count, + start, rpos - start); + } + + return pos; +} + + +u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, + size_t max_len, int auth_alg, + const u8 *req_ies, size_t req_ies_len) +{ + u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL; + size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0; int res; struct wpa_auth_config *conf; struct rsn_ftie *_ftie; + struct wpa_ft_ies parse; + u8 *ric_start; + u8 *anonce, *snonce; if (sm == NULL) return pos; @@ -491,13 +628,18 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, end = pos + max_len; - /* RSN */ - res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name); - if (res < 0) - return pos; - rsnie = pos; - rsnie_len = res; - pos += res; + if (auth_alg == WLAN_AUTH_FT) { + /* + * RSN (only present if this is a Reassociation Response and + * part of a fast BSS transition) + */ + res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name); + if (res < 0) + return pos; + rsnie = pos; + rsnie_len = res; + pos += res; + } /* Mobility Domain Information */ res = wpa_write_mdie(conf, pos, end - pos); @@ -512,6 +654,8 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, subelem = wpa_ft_gtk_subelem(sm, &subelem_len); r0kh_id = sm->r0kh_id; r0kh_id_len = sm->r0kh_id_len; + anonce = sm->ANonce; + snonce = sm->SNonce; #ifdef CONFIG_IEEE80211W if (sm->mgmt_frame_prot) { u8 *igtk; @@ -537,8 +681,10 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, } else { r0kh_id = conf->r0_key_holder; r0kh_id_len = conf->r0_key_holder_len; + anonce = NULL; + snonce = NULL; } - res = wpa_write_ftie(conf, r0kh_id, r0kh_id_len, NULL, NULL, pos, + res = wpa_write_ftie(conf, r0kh_id, r0kh_id_len, anonce, snonce, pos, end - pos, subelem, subelem_len); os_free(subelem); if (res < 0) @@ -547,33 +693,38 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, ftie_len = res; pos += res; + os_free(sm->assoc_resp_ftie); + sm->assoc_resp_ftie = os_malloc(ftie_len); + if (sm->assoc_resp_ftie) + os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len); + _ftie = (struct rsn_ftie *) (ftie + 2); - _ftie->mic_control[1] = 3; /* Information element count */ - if (wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 6, + if (auth_alg == WLAN_AUTH_FT) + _ftie->mic_control[1] = 3; /* Information element count */ + + ric_start = pos; + if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse) == 0 && parse.ric) { + pos = wpa_ft_process_ric(pos, end, parse.ric, parse.ric_len); + if (auth_alg == WLAN_AUTH_FT) + _ftie->mic_control[1] += + ieee802_11_ie_count(ric_start, + pos - ric_start); + } + if (ric_start == pos) + ric_start = NULL; + + if (auth_alg == WLAN_AUTH_FT && + wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 6, mdie, mdie_len, ftie, ftie_len, - rsnie, rsnie_len, NULL, 0, _ftie->mic) < 0) + rsnie, rsnie_len, + ric_start, ric_start ? pos - ric_start : 0, + _ftie->mic) < 0) wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); return pos; } -struct wpa_ft_ies { - const u8 *mdie; - size_t mdie_len; - const u8 *ftie; - size_t ftie_len; - const u8 *r1kh_id; - const u8 *gtk; - size_t gtk_len; - const u8 *r0kh_id; - size_t r0kh_id_len; - const u8 *rsn; - size_t rsn_len; - const u8 *rsn_pmkid; -}; - - static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, struct wpa_ft_ies *parse) { @@ -623,6 +774,8 @@ static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, const u8 *end, *pos; struct wpa_ie_data data; int ret; + const struct rsn_ftie *ftie; + int prot_ie_count = 0; os_memset(parse, 0, sizeof(*parse)); if (ies == NULL) @@ -651,21 +804,67 @@ static int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, parse->mdie_len = pos[1]; break; case WLAN_EID_FAST_BSS_TRANSITION: + if (pos[1] < sizeof(*ftie)) + return -1; + ftie = (const struct rsn_ftie *) (pos + 2); + prot_ie_count = ftie->mic_control[1]; if (wpa_ft_parse_ftie(pos + 2, pos[1], parse) < 0) return -1; break; + case WLAN_EID_RIC_DATA: + if (parse->ric == NULL) + parse->ric = pos; } pos += 2 + pos[1]; } + if (prot_ie_count == 0) + return 0; /* no MIC */ + + /* + * Check that the protected IE count matches with IEs included in the + * frame. + */ + if (parse->rsn) + prot_ie_count--; + if (parse->mdie) + prot_ie_count--; + if (parse->ftie) + prot_ie_count--; + if (prot_ie_count < 0) { + wpa_printf(MSG_DEBUG, "FT: Some required IEs not included in " + "the protected IE count"); + return -1; + } + + if (prot_ie_count == 0 && parse->ric) { + wpa_printf(MSG_DEBUG, "FT: RIC IE(s) in the frame, but not " + "included in protected IE count"); + return -1; + } + + /* Determine the end of the RIC IE(s) */ + pos = parse->ric; + while (pos && pos + 2 <= end && pos + 2 + pos[1] <= end && + prot_ie_count) { + prot_ie_count--; + pos += 2 + pos[1]; + } + parse->ric_len = pos - parse->ric; + if (prot_ie_count) { + wpa_printf(MSG_DEBUG, "FT: %d protected IEs missing from " + "frame", (int) prot_ie_count); + return -1; + } + return 0; } static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, int vlan_id, - const char *alg, const u8 *addr, int idx, + enum wpa_alg alg, const u8 *addr, int idx, u8 *key, size_t key_len) { if (wpa_auth->cb.set_key == NULL) @@ -675,25 +874,29 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, } -static void wpa_ft_install_ptk(struct wpa_state_machine *sm) +void wpa_ft_install_ptk(struct wpa_state_machine *sm) { - char *alg; + enum wpa_alg alg; int klen; /* MLME-SETKEYS.request(PTK) */ if (sm->pairwise == WPA_CIPHER_TKIP) { - alg = "TKIP"; + alg = WPA_ALG_TKIP; klen = 32; } else if (sm->pairwise == WPA_CIPHER_CCMP) { - alg = "CCMP"; + alg = WPA_ALG_CCMP; klen = 16; - } else + } else { + wpa_printf(MSG_DEBUG, "FT: Unknown pairwise alg 0x%x - skip " + "PTK configuration", sm->pairwise); return; + } /* FIX: add STA entry to kernel/driver here? The set_key will fail * most likely without this.. At the moment, STA entry is added only - * after association has been completed. Alternatively, could - * re-configure PTK at that point(?). + * after association has been completed. This function will be called + * again after association to get the PTK configured, but that could be + * optimized by adding the STA entry earlier. */ if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, sm->PTK.tk1, klen)) @@ -717,6 +920,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm, size_t buflen, ptk_len; int ret; u8 *pos, *end; + int pairwise; *resp_ies = NULL; *resp_ies_len = 0; @@ -772,8 +976,8 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm, wpa_hexdump(MSG_DEBUG, "FT: Derived requested PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); - if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name, pmk_r1) < - 0) { + if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name, pmk_r1, + &pairwise) < 0) { if (wpa_ft_pull_pmk_r1(sm->wpa_auth, sm->addr, sm->r0kh_id, sm->r0kh_id_len, parse.rsn_pmkid) < 0) { wpa_printf(MSG_DEBUG, "FT: Did not have matching " @@ -804,7 +1008,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm, wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce", sm->ANonce, WPA_NONCE_LEN); - ptk_len = sm->pairwise == WPA_CIPHER_CCMP ? 48 : 64; + ptk_len = pairwise != WPA_CIPHER_CCMP ? 64 : 48; wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, sm->wpa_auth->addr, pmk_r1_name, (u8 *) &sm->PTK, ptk_len, ptk_name); @@ -812,6 +1016,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm, (u8 *) &sm->PTK, ptk_len); wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); + sm->pairwise = pairwise; wpa_ft_install_ptk(sm); buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + @@ -895,6 +1100,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, struct rsn_mdie *mdie; struct rsn_ftie *ftie; u8 mic[16]; + unsigned int count; if (sm == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; @@ -938,20 +1144,79 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, return WLAN_STATUS_INVALID_FTIE; } - /* - * Assume that MDIE, FTIE, and RSN IE are protected and that there is - * no RIC, so total of 3 protected IEs. - */ - if (ftie->mic_control[1] != 3) { - wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in FTIE (%d)", - ftie->mic_control[1]); - return WLAN_STATUS_INVALID_FTIE; + if (os_memcmp(ftie->snonce, sm->SNonce, WPA_NONCE_LEN) != 0) { + wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE"); + wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", + ftie->snonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", + sm->SNonce, WPA_NONCE_LEN); + return -1; + } + + if (os_memcmp(ftie->anonce, sm->ANonce, WPA_NONCE_LEN) != 0) { + wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE"); + wpa_hexdump(MSG_DEBUG, "FT: Received ANonce", + ftie->anonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", + sm->ANonce, WPA_NONCE_LEN); + return -1; + } + + + if (parse.r0kh_id == NULL) { + wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE"); + return -1; + } + + if (parse.r0kh_id_len != sm->r0kh_id_len || + os_memcmp(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0) { + wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with " + "the current R0KH-ID"); + wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE", + parse.r0kh_id, parse.r0kh_id_len); + wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID", + sm->r0kh_id, sm->r0kh_id_len); + return -1; + } + + if (parse.r1kh_id == NULL) { + wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE"); + return -1; + } + + if (os_memcmp(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder, + FT_R1KH_ID_LEN) != 0) { + wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in " + "ReassocReq"); + wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID in FTIE", + parse.r1kh_id, FT_R1KH_ID_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID", + sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN); + return -1; + } + + if (parse.rsn_pmkid == NULL || + os_memcmp(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)) { + wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in " + "RSNIE (pmkid=%d)", !!parse.rsn_pmkid); + return -1; + } + + count = 3; + if (parse.ric) + count++; + if (ftie->mic_control[1] != count) { + wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC " + "Control: received %u expected %u", + ftie->mic_control[1], count); + return -1; } if (wpa_ft_mic(sm->PTK.kck, sm->addr, sm->wpa_auth->addr, 5, parse.mdie - 2, parse.mdie_len + 2, parse.ftie - 2, parse.ftie_len + 2, - parse.rsn - 2, parse.rsn_len + 2, NULL, 0, + parse.rsn - 2, parse.rsn_len + 2, + parse.ric, parse.ric_len, mic) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC"); return WLAN_STATUS_UNSPECIFIED_FAILURE; @@ -1107,6 +1372,7 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, struct ft_remote_r1kh *r1kh; struct ft_r0kh_r1kh_resp_frame resp, r; u8 pmk_r0[PMK_LEN]; + int pairwise; wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull"); @@ -1154,8 +1420,8 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, os_memcpy(r.nonce, f.nonce, sizeof(f.nonce)); os_memcpy(r.r1kh_id, f.r1kh_id, FT_R1KH_ID_LEN); os_memcpy(r.s1kh_id, f.s1kh_id, ETH_ALEN); - if (wpa_ft_fetch_pmk_r0(wpa_auth, f.s1kh_id, f.pmk_r0_name, pmk_r0) < - 0) { + if (wpa_ft_fetch_pmk_r0(wpa_auth, f.s1kh_id, f.pmk_r0_name, pmk_r0, + &pairwise) < 0) { wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name found for " "PMK-R1 pull"); return -1; @@ -1166,6 +1432,7 @@ static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth, wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", r.pmk_r1, PMK_LEN); wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", r.pmk_r1_name, WPA_PMK_NAME_LEN); + r.pairwise = host_to_le16(pairwise); if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, r.nonce, resp.nonce) < 0) { @@ -1187,6 +1454,7 @@ static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth, { struct ft_r0kh_r1kh_resp_frame *frame, f; struct ft_remote_r0kh *r0kh; + int pairwise; wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response"); @@ -1227,16 +1495,19 @@ static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth, * and call this requests callback function to finish request * processing */ + pairwise = le_to_host16(f.pairwise); wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce", f.nonce, sizeof(f.nonce)); wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR "S1KH-ID=" - MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id)); + MACSTR " pairwise=0x%x", + MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise); wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1", f.pmk_r1, PMK_LEN); wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name", f.pmk_r1_name, WPA_PMK_NAME_LEN); - wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name); + wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name, + pairwise); os_memset(f.pmk_r1, 0, PMK_LEN); return 0; @@ -1251,6 +1522,7 @@ static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth, struct ft_remote_r0kh *r0kh; struct os_time now; os_time_t tsend; + int pairwise; wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 push"); @@ -1299,14 +1571,17 @@ static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth, return -1; } + pairwise = le_to_host16(f.pairwise); wpa_printf(MSG_DEBUG, "FT: PMK-R1 push - R1KH-ID=" MACSTR " S1KH-ID=" - MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id)); + MACSTR " pairwise=0x%x", + MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise); wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 push - PMK-R1", f.pmk_r1, PMK_LEN); wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 push - PMKR1Name", f.pmk_r1_name, WPA_PMK_NAME_LEN); - wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name); + wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name, + pairwise); os_memset(f.pmk_r1, 0, PMK_LEN); return 0; @@ -1436,7 +1711,7 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth, struct wpa_ft_pmk_r0_sa *pmk_r0, struct ft_remote_r1kh *r1kh, - const u8 *s1kh_id) + const u8 *s1kh_id, int pairwise) { struct ft_r0kh_r1kh_push_frame frame, f; struct os_time now; @@ -1460,6 +1735,7 @@ static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth, WPA_PMK_NAME_LEN); os_get_time(&now); WPA_PUT_LE32(f.timestamp, now.sec); + f.pairwise = host_to_le16(pairwise); if (aes_wrap(r1kh->key, (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8, f.timestamp, frame.timestamp) < 0) return; @@ -1492,7 +1768,7 @@ void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr) r1kh = wpa_auth->conf.r1kh_list; while (r1kh) { - wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr); + wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr, r0->pairwise); r1kh = r1kh->next; } } diff --git a/contrib/wpa/src/ap/wpa_auth_glue.c b/contrib/wpa/src/ap/wpa_auth_glue.c new file mode 100644 index 000000000000..afa13a698bef --- /dev/null +++ b/contrib/wpa/src/ap/wpa_auth_glue.c @@ -0,0 +1,545 @@ +/* + * hostapd / WPA authenticator glue code + * Copyright (c) 2002-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "eapol_auth/eapol_auth_sm_i.h" +#include "eap_server/eap.h" +#include "l2_packet/l2_packet.h" +#include "drivers/driver.h" +#include "hostapd.h" +#include "ieee802_1x.h" +#include "preauth_auth.h" +#include "sta_info.h" +#include "tkip_countermeasures.h" +#include "ap_drv_ops.h" +#include "ap_config.h" +#include "wpa_auth.h" + + +#ifdef CONFIG_IEEE80211R +static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, + size_t len); +#endif /* CONFIG_IEEE80211R */ + + +static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, + struct wpa_auth_config *wconf) +{ + wconf->wpa = conf->wpa; + wconf->wpa_key_mgmt = conf->wpa_key_mgmt; + wconf->wpa_pairwise = conf->wpa_pairwise; + wconf->wpa_group = conf->wpa_group; + wconf->wpa_group_rekey = conf->wpa_group_rekey; + wconf->wpa_strict_rekey = conf->wpa_strict_rekey; + wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey; + wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey; + wconf->rsn_pairwise = conf->rsn_pairwise; + wconf->rsn_preauth = conf->rsn_preauth; + wconf->eapol_version = conf->eapol_version; + wconf->peerkey = conf->peerkey; + wconf->wmm_enabled = conf->wmm_enabled; + wconf->wmm_uapsd = conf->wmm_uapsd; + wconf->okc = conf->okc; +#ifdef CONFIG_IEEE80211W + wconf->ieee80211w = conf->ieee80211w; +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_IEEE80211R + wconf->ssid_len = conf->ssid.ssid_len; + if (wconf->ssid_len > SSID_LEN) + wconf->ssid_len = SSID_LEN; + os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len); + os_memcpy(wconf->mobility_domain, conf->mobility_domain, + MOBILITY_DOMAIN_ID_LEN); + if (conf->nas_identifier && + os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) { + wconf->r0_key_holder_len = os_strlen(conf->nas_identifier); + os_memcpy(wconf->r0_key_holder, conf->nas_identifier, + wconf->r0_key_holder_len); + } + os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN); + wconf->r0_key_lifetime = conf->r0_key_lifetime; + wconf->reassociation_deadline = conf->reassociation_deadline; + wconf->r0kh_list = conf->r0kh_list; + wconf->r1kh_list = conf->r1kh_list; + wconf->pmk_r1_push = conf->pmk_r1_push; +#endif /* CONFIG_IEEE80211R */ +} + + +static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr, + logger_level level, const char *txt) +{ +#ifndef CONFIG_NO_HOSTAPD_LOGGER + struct hostapd_data *hapd = ctx; + int hlevel; + + switch (level) { + case LOGGER_WARNING: + hlevel = HOSTAPD_LEVEL_WARNING; + break; + case LOGGER_INFO: + hlevel = HOSTAPD_LEVEL_INFO; + break; + case LOGGER_DEBUG: + default: + hlevel = HOSTAPD_LEVEL_DEBUG; + break; + } + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt); +#endif /* CONFIG_NO_HOSTAPD_LOGGER */ +} + + +static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr, + u16 reason) +{ + struct hostapd_data *hapd = ctx; + wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: " + "STA " MACSTR " reason %d", + __func__, MAC2STR(addr), reason); + ap_sta_disconnect(hapd, NULL, addr, reason); +} + + +static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) +{ + struct hostapd_data *hapd = ctx; + michael_mic_failure(hapd, addr, 0); +} + + +static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr, + wpa_eapol_variable var, int value) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta = ap_get_sta(hapd, addr); + if (sta == NULL) + return; + switch (var) { + case WPA_EAPOL_portEnabled: + ieee802_1x_notify_port_enabled(sta->eapol_sm, value); + break; + case WPA_EAPOL_portValid: + ieee802_1x_notify_port_valid(sta->eapol_sm, value); + break; + case WPA_EAPOL_authorized: + ieee802_1x_set_sta_authorized(hapd, sta, value); + break; + case WPA_EAPOL_portControl_Auto: + if (sta->eapol_sm) + sta->eapol_sm->portControl = Auto; + break; + case WPA_EAPOL_keyRun: + if (sta->eapol_sm) + sta->eapol_sm->keyRun = value ? TRUE : FALSE; + break; + case WPA_EAPOL_keyAvailable: + if (sta->eapol_sm) + sta->eapol_sm->eap_if->eapKeyAvailable = + value ? TRUE : FALSE; + break; + case WPA_EAPOL_keyDone: + if (sta->eapol_sm) + sta->eapol_sm->keyDone = value ? TRUE : FALSE; + break; + case WPA_EAPOL_inc_EapolFramesTx: + if (sta->eapol_sm) + sta->eapol_sm->dot1xAuthEapolFramesTx++; + break; + } +} + + +static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr, + wpa_eapol_variable var) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta = ap_get_sta(hapd, addr); + if (sta == NULL || sta->eapol_sm == NULL) + return -1; + switch (var) { + case WPA_EAPOL_keyRun: + return sta->eapol_sm->keyRun; + case WPA_EAPOL_keyAvailable: + return sta->eapol_sm->eap_if->eapKeyAvailable; + default: + return -1; + } +} + + +static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, + const u8 *prev_psk) +{ + struct hostapd_data *hapd = ctx; + return hostapd_get_psk(hapd->conf, addr, prev_psk); +} + + +static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk, + size_t *len) +{ + struct hostapd_data *hapd = ctx; + const u8 *key; + size_t keylen; + struct sta_info *sta; + + sta = ap_get_sta(hapd, addr); + if (sta == NULL) + return -1; + + key = ieee802_1x_get_key(sta->eapol_sm, &keylen); + if (key == NULL) + return -1; + + if (keylen > *len) + keylen = *len; + os_memcpy(msk, key, keylen); + *len = keylen; + + return 0; +} + + +static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, + const u8 *addr, int idx, u8 *key, + size_t key_len) +{ + struct hostapd_data *hapd = ctx; + const char *ifname = hapd->conf->iface; + + if (vlan_id > 0) { + ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); + if (ifname == NULL) + return -1; + } + + return hapd->drv.set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0, + key, key_len); +} + + +static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx, + u8 *seq) +{ + struct hostapd_data *hapd = ctx; + return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq); +} + + +static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr, + const u8 *data, size_t data_len, + int encrypt) +{ + struct hostapd_data *hapd = ctx; + return hapd->drv.send_eapol(hapd, addr, data, data_len, encrypt); +} + + +static int hostapd_wpa_auth_for_each_sta( + void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx), + void *cb_ctx) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx)) + return 1; + } + return 0; +} + + +struct wpa_auth_iface_iter_data { + int (*cb)(struct wpa_authenticator *sm, void *ctx); + void *cb_ctx; +}; + +static int wpa_auth_iface_iter(struct hostapd_iface *iface, void *ctx) +{ + struct wpa_auth_iface_iter_data *data = ctx; + size_t i; + for (i = 0; i < iface->num_bss; i++) { + if (iface->bss[i]->wpa_auth && + data->cb(iface->bss[i]->wpa_auth, data->cb_ctx)) + return 1; + } + return 0; +} + + +static int hostapd_wpa_auth_for_each_auth( + void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx), + void *cb_ctx) +{ + struct hostapd_data *hapd = ctx; + struct wpa_auth_iface_iter_data data; + if (hapd->iface->for_each_interface == NULL) + return -1; + data.cb = cb; + data.cb_ctx = cb_ctx; + return hapd->iface->for_each_interface(hapd->iface->interfaces, + wpa_auth_iface_iter, &data); +} + + +#ifdef CONFIG_IEEE80211R + +struct wpa_auth_ft_iface_iter_data { + struct hostapd_data *src_hapd; + const u8 *dst; + const u8 *data; + size_t data_len; +}; + + +static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx) +{ + struct wpa_auth_ft_iface_iter_data *idata = ctx; + struct hostapd_data *hapd; + size_t j; + + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + if (hapd == idata->src_hapd) + continue; + if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0) { + wpa_printf(MSG_DEBUG, "FT: Send RRB data directly to " + "locally managed BSS " MACSTR "@%s -> " + MACSTR "@%s", + MAC2STR(idata->src_hapd->own_addr), + idata->src_hapd->conf->iface, + MAC2STR(hapd->own_addr), hapd->conf->iface); + hostapd_rrb_receive(hapd, idata->src_hapd->own_addr, + idata->data, idata->data_len); + return 1; + } + } + + return 0; +} + +#endif /* CONFIG_IEEE80211R */ + + +static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto, + const u8 *data, size_t data_len) +{ + struct hostapd_data *hapd = ctx; + +#ifdef CONFIG_IEEE80211R + if (proto == ETH_P_RRB && hapd->iface->for_each_interface) { + int res; + struct wpa_auth_ft_iface_iter_data idata; + idata.src_hapd = hapd; + idata.dst = dst; + idata.data = data; + idata.data_len = data_len; + res = hapd->iface->for_each_interface(hapd->iface->interfaces, + hostapd_wpa_auth_ft_iter, + &idata); + if (res == 1) + return data_len; + } +#endif /* CONFIG_IEEE80211R */ + + if (hapd->driver && hapd->driver->send_ether) + return hapd->driver->send_ether(hapd->drv_priv, dst, + hapd->own_addr, proto, + data, data_len); + if (hapd->l2 == NULL) + return -1; + return l2_packet_send(hapd->l2, dst, proto, data, data_len); +} + + +#ifdef CONFIG_IEEE80211R + +static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst, + const u8 *data, size_t data_len) +{ + struct hostapd_data *hapd = ctx; + int res; + struct ieee80211_mgmt *m; + size_t mlen; + struct sta_info *sta; + + sta = ap_get_sta(hapd, dst); + if (sta == NULL || sta->wpa_sm == NULL) + return -1; + + m = os_zalloc(sizeof(*m) + data_len); + if (m == NULL) + return -1; + mlen = ((u8 *) &m->u - (u8 *) m) + data_len; + m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(m->da, dst, ETH_ALEN); + os_memcpy(m->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); + os_memcpy(&m->u, data, data_len); + + res = hapd->drv.send_mgmt_frame(hapd, (u8 *) m, mlen); + os_free(m); + return res; +} + + +static struct wpa_state_machine * +hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + + sta = ap_sta_add(hapd, sta_addr); + if (sta == NULL) + return NULL; + if (sta->wpa_sm) { + sta->auth_alg = WLAN_AUTH_FT; + return sta->wpa_sm; + } + + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr); + if (sta->wpa_sm == NULL) { + ap_free_sta(hapd, sta); + return NULL; + } + sta->auth_alg = WLAN_AUTH_FT; + + return sta->wpa_sm; +} + + +static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, + size_t len) +{ + struct hostapd_data *hapd = ctx; + wpa_ft_rrb_rx(hapd->wpa_auth, src_addr, buf, len); +} + +#endif /* CONFIG_IEEE80211R */ + + +int hostapd_setup_wpa(struct hostapd_data *hapd) +{ + struct wpa_auth_config _conf; + struct wpa_auth_callbacks cb; + const u8 *wpa_ie; + size_t wpa_ie_len; + + hostapd_wpa_auth_conf(hapd->conf, &_conf); + os_memset(&cb, 0, sizeof(cb)); + cb.ctx = hapd; + cb.logger = hostapd_wpa_auth_logger; + cb.disconnect = hostapd_wpa_auth_disconnect; + cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report; + cb.set_eapol = hostapd_wpa_auth_set_eapol; + cb.get_eapol = hostapd_wpa_auth_get_eapol; + cb.get_psk = hostapd_wpa_auth_get_psk; + cb.get_msk = hostapd_wpa_auth_get_msk; + cb.set_key = hostapd_wpa_auth_set_key; + cb.get_seqnum = hostapd_wpa_auth_get_seqnum; + cb.send_eapol = hostapd_wpa_auth_send_eapol; + cb.for_each_sta = hostapd_wpa_auth_for_each_sta; + cb.for_each_auth = hostapd_wpa_auth_for_each_auth; + cb.send_ether = hostapd_wpa_auth_send_ether; +#ifdef CONFIG_IEEE80211R + cb.send_ft_action = hostapd_wpa_auth_send_ft_action; + cb.add_sta = hostapd_wpa_auth_add_sta; +#endif /* CONFIG_IEEE80211R */ + hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb); + if (hapd->wpa_auth == NULL) { + wpa_printf(MSG_ERROR, "WPA initialization failed."); + return -1; + } + + if (hostapd_set_privacy(hapd, 1)) { + wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked " + "for interface %s", hapd->conf->iface); + return -1; + } + + wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); + if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) { + wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " + "the kernel driver."); + return -1; + } + + if (rsn_preauth_iface_init(hapd)) { + wpa_printf(MSG_ERROR, "Initialization of RSN " + "pre-authentication failed."); + return -1; + } + +#ifdef CONFIG_IEEE80211R + if (!hostapd_drv_none(hapd)) { + hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ? + hapd->conf->bridge : + hapd->conf->iface, NULL, ETH_P_RRB, + hostapd_rrb_receive, hapd, 0); + if (hapd->l2 == NULL && + (hapd->driver == NULL || + hapd->driver->send_ether == NULL)) { + wpa_printf(MSG_ERROR, "Failed to open l2_packet " + "interface"); + return -1; + } + } +#endif /* CONFIG_IEEE80211R */ + + return 0; + +} + + +void hostapd_reconfig_wpa(struct hostapd_data *hapd) +{ + struct wpa_auth_config wpa_auth_conf; + hostapd_wpa_auth_conf(hapd->conf, &wpa_auth_conf); + wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf); +} + + +void hostapd_deinit_wpa(struct hostapd_data *hapd) +{ + rsn_preauth_iface_deinit(hapd); + if (hapd->wpa_auth) { + wpa_deinit(hapd->wpa_auth); + hapd->wpa_auth = NULL; + + if (hostapd_set_privacy(hapd, 0)) { + wpa_printf(MSG_DEBUG, "Could not disable " + "PrivacyInvoked for interface %s", + hapd->conf->iface); + } + + if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) { + wpa_printf(MSG_DEBUG, "Could not remove generic " + "information element from interface %s", + hapd->conf->iface); + } + } + ieee802_1x_deinit(hapd); + +#ifdef CONFIG_IEEE80211R + l2_packet_deinit(hapd->l2); +#endif /* CONFIG_IEEE80211R */ +} diff --git a/contrib/wpa/src/ap/wpa_auth_glue.h b/contrib/wpa/src/ap/wpa_auth_glue.h new file mode 100644 index 000000000000..79d7e05c4055 --- /dev/null +++ b/contrib/wpa/src/ap/wpa_auth_glue.h @@ -0,0 +1,22 @@ +/* + * hostapd / WPA authenticator glue code + * Copyright (c) 2002-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef WPA_AUTH_GLUE_H +#define WPA_AUTH_GLUE_H + +int hostapd_setup_wpa(struct hostapd_data *hapd); +void hostapd_reconfig_wpa(struct hostapd_data *hapd); +void hostapd_deinit_wpa(struct hostapd_data *hapd); + +#endif /* WPA_AUTH_GLUE_H */ diff --git a/contrib/wpa/hostapd/wpa_auth_i.h b/contrib/wpa/src/ap/wpa_auth_i.h similarity index 94% rename from contrib/wpa/hostapd/wpa_auth_i.h rename to contrib/wpa/src/ap/wpa_auth_i.h index 925d3ee459ce..b69129ff44cf 100644 --- a/contrib/wpa/hostapd/wpa_auth_i.h +++ b/contrib/wpa/src/ap/wpa_auth_i.h @@ -116,6 +116,9 @@ struct wpa_state_machine { * Request */ u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; /* R0KH-ID from FT Auth Request */ size_t r0kh_id_len; + u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key + * message 2/4 */ + u8 *assoc_resp_ftie; #endif /* CONFIG_IEEE80211R */ }; @@ -212,10 +215,16 @@ void wpa_smk_m3(struct wpa_authenticator *wpa_auth, #ifdef CONFIG_IEEE80211R int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len); +int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, + size_t r0kh_id_len, + const u8 *anonce, const u8 *snonce, + u8 *buf, size_t len, const u8 *subelem, + size_t subelem_len); int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, struct wpa_ptk *ptk, size_t ptk_len); struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void); void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache); +void wpa_ft_install_ptk(struct wpa_state_machine *sm); #endif /* CONFIG_IEEE80211R */ #endif /* WPA_AUTH_I_H */ diff --git a/contrib/wpa/hostapd/wpa_auth_ie.c b/contrib/wpa/src/ap/wpa_auth_ie.c similarity index 97% rename from contrib/wpa/hostapd/wpa_auth_ie.c rename to contrib/wpa/src/ap/wpa_auth_ie.c index 7e0163528455..f8a1804c9f71 100644 --- a/contrib/wpa/hostapd/wpa_auth_ie.c +++ b/contrib/wpa/src/ap/wpa_auth_ie.c @@ -12,14 +12,15 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" -#include "common.h" -#include "config.h" +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "ap_config.h" #include "ieee802_11.h" -#include "eapol_sm.h" -#include "wpa.h" -#include "pmksa_cache.h" +#include "wpa_auth.h" +#include "pmksa_cache_auth.h" #include "wpa_auth_ie.h" #include "wpa_auth_i.h" @@ -220,9 +221,9 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); } #ifdef CONFIG_IEEE80211W - if (conf->ieee80211w != WPA_NO_IEEE80211W) { + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { capab |= WPA_CAPABILITY_MFPC; - if (conf->ieee80211w == IEEE80211W_REQUIRED) + if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) capab |= WPA_CAPABILITY_MFPR; } #endif /* CONFIG_IEEE80211W */ @@ -240,7 +241,7 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, } #ifdef CONFIG_IEEE80211W - if (conf->ieee80211w != WPA_NO_IEEE80211W) { + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { if (pos + 2 + 4 > buf + len) return -1; if (pmkid == NULL) { @@ -612,7 +613,7 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, } #ifdef CONFIG_IEEE80211W - if (wpa_auth->conf.ieee80211w == WPA_IEEE80211W_REQUIRED) { + if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) { if (!(data.capabilities & WPA_CAPABILITY_MFPC)) { wpa_printf(MSG_DEBUG, "Management frame protection " "required, but client did not enable it"); @@ -632,7 +633,7 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, } } - if (wpa_auth->conf.ieee80211w == WPA_NO_IEEE80211W || + if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION || !(data.capabilities & WPA_CAPABILITY_MFPC)) sm->mgmt_frame_prot = 0; else @@ -670,8 +671,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, for (i = 0; i < data.num_pmkid; i++) { wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID", &data.pmkid[i * PMKID_LEN], PMKID_LEN); - sm->pmksa = pmksa_cache_get(wpa_auth->pmksa, sm->addr, - &data.pmkid[i * PMKID_LEN]); + sm->pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sm->addr, + &data.pmkid[i * PMKID_LEN]); if (sm->pmksa) { pmkid = sm->pmksa->pmkid; break; @@ -839,6 +840,9 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { ie->mdie = pos; ie->mdie_len = pos[1] + 2; + } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { + ie->ftie = pos; + ie->ftie_len = pos[1] + 2; #endif /* CONFIG_IEEE80211R */ } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { ret = wpa_parse_generic(pos, end, ie); diff --git a/contrib/wpa/hostapd/wpa_auth_ie.h b/contrib/wpa/src/ap/wpa_auth_ie.h similarity index 97% rename from contrib/wpa/hostapd/wpa_auth_ie.h rename to contrib/wpa/src/ap/wpa_auth_ie.h index 9968d2d92a16..61d4cb4075fe 100644 --- a/contrib/wpa/hostapd/wpa_auth_ie.h +++ b/contrib/wpa/src/ap/wpa_auth_ie.h @@ -42,6 +42,8 @@ struct wpa_eapol_ie_parse { #ifdef CONFIG_IEEE80211R const u8 *mdie; size_t mdie_len; + const u8 *ftie; + size_t ftie_len; #endif /* CONFIG_IEEE80211R */ }; diff --git a/contrib/wpa/hostapd/wps_hostapd.c b/contrib/wpa/src/ap/wps_hostapd.c similarity index 69% rename from contrib/wpa/hostapd/wps_hostapd.c rename to contrib/wpa/src/ap/wps_hostapd.c index 818767ef46fa..a6ffd4d0db0b 100644 --- a/contrib/wpa/hostapd/wps_hostapd.c +++ b/contrib/wpa/src/ap/wps_hostapd.c @@ -1,6 +1,6 @@ /* * hostapd / WPS integration - * Copyright (c) 2008, Jouni Malinen + * Copyright (c) 2008-2010, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -12,19 +12,24 @@ * See README and COPYING for more details. */ -#include "includes.h" +#include "utils/includes.h" -#include "hostapd.h" -#include "driver.h" -#include "eloop.h" -#include "uuid.h" -#include "wpa_ctrl.h" -#include "ieee802_11_defs.h" -#include "sta_info.h" -#include "eapol_sm.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "utils/uuid.h" +#include "crypto/dh_groups.h" +#include "common/wpa_ctrl.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "eapol_auth/eapol_auth_sm_i.h" #include "wps/wps.h" #include "wps/wps_defs.h" #include "wps/wps_dev_attr.h" +#include "hostapd.h" +#include "ap_config.h" +#include "beacon.h" +#include "sta_info.h" #include "wps_hostapd.h" @@ -35,6 +40,10 @@ static int hostapd_wps_upnp_init(struct hostapd_data *hapd, static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd); #endif /* CONFIG_WPS_UPNP */ +static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, + const u8 *ie, size_t ie_len); +static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx); + static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk, size_t psk_len) @@ -83,46 +92,16 @@ static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk, } -static int hostapd_wps_set_ie_cb(void *ctx, const u8 *beacon_ie, - size_t beacon_ie_len, const u8 *probe_resp_ie, - size_t probe_resp_ie_len) +static int hostapd_wps_set_ie_cb(void *ctx, struct wpabuf *beacon_ie, + struct wpabuf *probe_resp_ie) { struct hostapd_data *hapd = ctx; - - os_free(hapd->wps_beacon_ie); - if (beacon_ie_len == 0) { - hapd->wps_beacon_ie = NULL; - hapd->wps_beacon_ie_len = 0; - } else { - hapd->wps_beacon_ie = os_malloc(beacon_ie_len); - if (hapd->wps_beacon_ie == NULL) { - hapd->wps_beacon_ie_len = 0; - return -1; - } - os_memcpy(hapd->wps_beacon_ie, beacon_ie, beacon_ie_len); - hapd->wps_beacon_ie_len = beacon_ie_len; - } - hostapd_set_wps_beacon_ie(hapd, hapd->wps_beacon_ie, - hapd->wps_beacon_ie_len); - - os_free(hapd->wps_probe_resp_ie); - if (probe_resp_ie_len == 0) { - hapd->wps_probe_resp_ie = NULL; - hapd->wps_probe_resp_ie_len = 0; - } else { - hapd->wps_probe_resp_ie = os_malloc(probe_resp_ie_len); - if (hapd->wps_probe_resp_ie == NULL) { - hapd->wps_probe_resp_ie_len = 0; - return -1; - } - os_memcpy(hapd->wps_probe_resp_ie, probe_resp_ie, - probe_resp_ie_len); - hapd->wps_probe_resp_ie_len = probe_resp_ie_len; - } - hostapd_set_wps_probe_resp_ie(hapd, hapd->wps_probe_resp_ie, - hapd->wps_probe_resp_ie_len); - - return 0; + wpabuf_free(hapd->wps_beacon_ie); + hapd->wps_beacon_ie = beacon_ie; + wpabuf_free(hapd->wps_probe_resp_ie); + hapd->wps_probe_resp_ie = probe_resp_ie; + ieee802_11_set_beacon(hapd); + return hapd->drv.set_ap_wps_ie(hapd); } @@ -132,17 +111,19 @@ static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e, struct hostapd_data *hapd = ctx; char uuid[40], txt[400]; int len; + char devtype[WPS_DEV_TYPE_BUFSIZE]; if (uuid_bin2str(uuid_e, uuid, sizeof(uuid))) return; wpa_printf(MSG_DEBUG, "WPS: PIN needed for E-UUID %s", uuid); len = os_snprintf(txt, sizeof(txt), WPS_EVENT_PIN_NEEDED - "%s " MACSTR " [%s|%s|%s|%s|%s|%d-%08X-%d]", + "%s " MACSTR " [%s|%s|%s|%s|%s|%s]", uuid, MAC2STR(dev->mac_addr), dev->device_name, dev->manufacturer, dev->model_name, dev->model_number, dev->serial_number, - dev->categ, dev->oui, dev->sub_categ); + wps_dev_type_bin2str(dev->pri_dev_type, devtype, + sizeof(devtype))); if (len > 0 && len < (int) sizeof(txt)) - wpa_msg(hapd, MSG_INFO, "%s", txt); + wpa_msg(hapd->msg_ctx, MSG_INFO, "%s", txt); if (hapd->conf->wps_pin_requests) { FILE *f; @@ -152,11 +133,12 @@ static void hostapd_wps_pin_needed_cb(void *ctx, const u8 *uuid_e, return; os_get_time(&t); fprintf(f, "%ld\t%s\t" MACSTR "\t%s\t%s\t%s\t%s\t%s" - "\t%d-%08X-%d\n", + "\t%s\n", t.sec, uuid, MAC2STR(dev->mac_addr), dev->device_name, dev->manufacturer, dev->model_name, dev->model_number, dev->serial_number, - dev->categ, dev->oui, dev->sub_categ); + wps_dev_type_bin2str(dev->pri_dev_type, devtype, + sizeof(devtype))); fclose(f); } } @@ -169,8 +151,34 @@ static void hostapd_wps_reg_success_cb(void *ctx, const u8 *mac_addr, char uuid[40]; if (uuid_bin2str(uuid_e, uuid, sizeof(uuid))) return; - wpa_msg(hapd, MSG_INFO, WPS_EVENT_REG_SUCCESS MACSTR " %s", + wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_REG_SUCCESS MACSTR " %s", MAC2STR(mac_addr), uuid); + if (hapd->wps_reg_success_cb) + hapd->wps_reg_success_cb(hapd->wps_reg_success_cb_ctx, + mac_addr, uuid_e); +} + + +static void hostapd_wps_enrollee_seen_cb(void *ctx, const u8 *addr, + const u8 *uuid_e, + const u8 *pri_dev_type, + u16 config_methods, + u16 dev_password_id, u8 request_type, + const char *dev_name) +{ + struct hostapd_data *hapd = ctx; + char uuid[40]; + char devtype[WPS_DEV_TYPE_BUFSIZE]; + if (uuid_bin2str(uuid_e, uuid, sizeof(uuid))) + return; + if (dev_name == NULL) + dev_name = ""; + wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, WPS_EVENT_ENROLLEE_SEEN MACSTR + " %s %s 0x%x %u %u [%s]", + MAC2STR(addr), uuid, + wps_dev_type_bin2str(pri_dev_type, devtype, + sizeof(devtype)), + config_methods, dev_password_id, request_type, dev_name); } @@ -185,7 +193,7 @@ static void wps_reload_config(void *eloop_data, void *user_ctx) struct hostapd_iface *iface = eloop_data; wpa_printf(MSG_DEBUG, "WPS: Reload configuration data"); - if (hostapd_reload_config(iface) < 0) { + if (iface->reload_config(iface) < 0) { wpa_printf(MSG_WARNING, "WPS: Failed to reload the updated " "configuration"); } @@ -223,12 +231,12 @@ static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred) if (_buf) { wpa_snprintf_hex(_buf, blen, cred->cred_attr, cred->cred_attr_len); - wpa_msg(hapd, MSG_INFO, "%s%s", + wpa_msg(hapd->msg_ctx, MSG_INFO, "%s%s", WPS_EVENT_NEW_AP_SETTINGS, _buf); os_free(_buf); } } else - wpa_msg(hapd, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS); + wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS); if (hapd->conf->wps_cred_processing == 1) return 0; @@ -414,44 +422,58 @@ static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred) } +static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx) +{ + struct hostapd_data *hapd = eloop_data; + + if (hapd->conf->ap_setup_locked) + return; + + wpa_printf(MSG_DEBUG, "WPS: Re-enable AP PIN"); + wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED); + hapd->wps->ap_setup_locked = 0; + wps_registrar_update_ie(hapd->wps->registrar); +} + + static void hostapd_pwd_auth_fail(struct hostapd_data *hapd, struct wps_event_pwd_auth_fail *data) { - FILE *f; - - if (!data->enrollee) + if (!data->enrollee || hapd->conf->ap_pin == NULL) return; /* * Registrar failed to prove its knowledge of the AP PIN. Lock AP setup - * if this happens multiple times. + * for some time if this happens multiple times to slow down brute + * force attacks. */ hapd->ap_pin_failures++; - if (hapd->ap_pin_failures < 4) + wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u", + hapd->ap_pin_failures); + if (hapd->ap_pin_failures < 3) return; - wpa_msg(hapd, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED); + wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED); hapd->wps->ap_setup_locked = 1; wps_registrar_update_ie(hapd->wps->registrar); - if (hapd->conf->wps_cred_processing == 1) - return; + if (!hapd->conf->ap_setup_locked) { + if (hapd->ap_pin_lockout_time == 0) + hapd->ap_pin_lockout_time = 60; + else if (hapd->ap_pin_lockout_time < 365 * 24 * 60 * 60 && + (hapd->ap_pin_failures % 3) == 0) + hapd->ap_pin_lockout_time *= 2; - f = fopen(hapd->iface->config_fname, "a"); - if (f == NULL) { - wpa_printf(MSG_WARNING, "WPS: Could not append to the current " - "configuration file"); - return; + wpa_printf(MSG_DEBUG, "WPS: Disable AP PIN for %u seconds", + hapd->ap_pin_lockout_time); + eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL); + eloop_register_timeout(hapd->ap_pin_lockout_time, 0, + hostapd_wps_reenable_ap_pin, hapd, + NULL); } - fprintf(f, "# WPS AP Setup Locked based on possible attack\n"); - fprintf(f, "ap_setup_locked=1\n"); - fclose(f); - - /* TODO: dualband AP may need to update multiple configuration files */ - - wpa_printf(MSG_DEBUG, "WPS: AP configuration updated"); + /* TODO: dualband AP may need to update other interfaces */ } @@ -467,15 +489,13 @@ static void hostapd_wps_event_cb(void *ctx, enum wps_event event, static void hostapd_wps_clear_ies(struct hostapd_data *hapd) { - os_free(hapd->wps_beacon_ie); + wpabuf_free(hapd->wps_beacon_ie); hapd->wps_beacon_ie = NULL; - hapd->wps_beacon_ie_len = 0; - hostapd_set_wps_beacon_ie(hapd, NULL, 0); - os_free(hapd->wps_probe_resp_ie); + wpabuf_free(hapd->wps_probe_resp_ie); hapd->wps_probe_resp_ie = NULL; - hapd->wps_probe_resp_ie_len = 0; - hostapd_set_wps_probe_resp_ie(hapd, NULL, 0); + + hapd->drv.set_ap_wps_ie(hapd); } @@ -521,43 +541,14 @@ int hostapd_init_wps(struct hostapd_data *hapd, os_strdup(hapd->conf->model_number) : NULL; wps->dev.serial_number = hapd->conf->serial_number ? os_strdup(hapd->conf->serial_number) : NULL; - if (hapd->conf->config_methods) { - char *m = hapd->conf->config_methods; - if (os_strstr(m, "label")) - wps->config_methods |= WPS_CONFIG_LABEL; - if (os_strstr(m, "display")) - wps->config_methods |= WPS_CONFIG_DISPLAY; - if (os_strstr(m, "push_button")) - wps->config_methods |= WPS_CONFIG_PUSHBUTTON; - if (os_strstr(m, "keypad")) - wps->config_methods |= WPS_CONFIG_KEYPAD; - } - if (hapd->conf->device_type) { - char *pos; - u8 oui[4]; - /* - - */ - wps->dev.categ = atoi(hapd->conf->device_type); - pos = os_strchr(hapd->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->config_methods = + wps_config_methods_str2bin(hapd->conf->config_methods); + if (hapd->conf->device_type && + wps_dev_type_str2bin(hapd->conf->device_type, + wps->dev.pri_dev_type) < 0) { + wpa_printf(MSG_ERROR, "WPS: Invalid device_type"); + os_free(wps); + return -1; } wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version); wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ? @@ -629,6 +620,11 @@ int hostapd_init_wps(struct hostapd_data *hapd, wps->network_key_len = conf->ssid.wep.len[0]; } + if (conf->ssid.wpa_psk) { + os_memcpy(wps->psk, conf->ssid.wpa_psk->psk, PMK_LEN); + wps->psk_set = 1; + } + if (conf->wps_state == WPS_STATE_NOT_CONFIGURED) { /* Override parameters to enable security by default */ wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK; @@ -642,6 +638,7 @@ int hostapd_init_wps(struct hostapd_data *hapd, cfg.set_ie_cb = hostapd_wps_set_ie_cb; cfg.pin_needed_cb = hostapd_wps_pin_needed_cb; cfg.reg_success_cb = hostapd_wps_reg_success_cb; + cfg.enrollee_seen_cb = hostapd_wps_enrollee_seen_cb; cfg.cb_ctx = hapd; cfg.skip_cred_build = conf->skip_cred_build; cfg.extra_cred = conf->extra_cred; @@ -675,6 +672,8 @@ int hostapd_init_wps(struct hostapd_data *hapd, } #endif /* CONFIG_WPS_UPNP */ + hostapd_register_probereq_cb(hapd, hostapd_wps_probe_req_rx, hapd); + hapd->wps = wps; return 0; @@ -683,6 +682,8 @@ int hostapd_init_wps(struct hostapd_data *hapd, void hostapd_deinit_wps(struct hostapd_data *hapd) { + eloop_cancel_timeout(hostapd_wps_reenable_ap_pin, hapd, NULL); + eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL); if (hapd->wps == NULL) return; #ifdef CONFIG_WPS_UPNP @@ -691,6 +692,10 @@ void hostapd_deinit_wps(struct hostapd_data *hapd) wps_registrar_deinit(hapd->wps->registrar); os_free(hapd->wps->network_key); wps_device_data_free(&hapd->wps->dev); + wpabuf_free(hapd->wps->dh_pubkey); + wpabuf_free(hapd->wps->dh_privkey); + wpabuf_free(hapd->wps->oob_conf.pubkey_hash); + wpabuf_free(hapd->wps->oob_conf.dev_password); wps_free_pending_msgs(hapd->wps->upnp_msgs); os_free(hapd->wps); hapd->wps = NULL; @@ -698,6 +703,17 @@ void hostapd_deinit_wps(struct hostapd_data *hapd) } +void hostapd_update_wps(struct hostapd_data *hapd) +{ + if (hapd->wps == NULL) + return; + if (hapd->conf->wps_state) + wps_registrar_update_ie(hapd->wps->registrar); + else + hostapd_deinit_wps(hapd); +} + + int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid, const char *pin, int timeout) { @@ -724,47 +740,85 @@ int hostapd_wps_button_pushed(struct hostapd_data *hapd) } -void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr, - const u8 *ie, size_t ie_len) +#ifdef CONFIG_WPS_OOB +int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type, + char *path, char *method, char *name) { + struct wps_context *wps = hapd->wps; + struct oob_device_data *oob_dev; + + oob_dev = wps_get_oob_device(device_type); + if (oob_dev == NULL) + return -1; + oob_dev->device_path = path; + oob_dev->device_name = name; + wps->oob_conf.oob_method = wps_get_oob_method(method); + + if (wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) { + /* + * Use pre-configured DH keys in order to be able to write the + * key hash into the OOB file. + */ + wpabuf_free(wps->dh_pubkey); + wpabuf_free(wps->dh_privkey); + wps->dh_privkey = NULL; + wps->dh_pubkey = dh_init(dh_groups_get(WPS_DH_GROUP), + &wps->dh_privkey); + wps->dh_pubkey = wpabuf_zeropad(wps->dh_pubkey, 192); + if (wps->dh_pubkey == NULL) { + wpa_printf(MSG_ERROR, "WPS: Failed to initialize " + "Diffie-Hellman handshake"); + return -1; + } + } + + if (wps_process_oob(wps, oob_dev, 1) < 0) + goto error; + + if ((wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_E || + wps->oob_conf.oob_method == OOB_METHOD_DEV_PWD_R) && + hostapd_wps_add_pin(hapd, "any", + wpabuf_head(wps->oob_conf.dev_password), 0) < + 0) + goto error; + + return 0; + +error: + wpabuf_free(wps->dh_pubkey); + wps->dh_pubkey = NULL; + wpabuf_free(wps->dh_privkey); + wps->dh_privkey = NULL; + return -1; +} +#endif /* CONFIG_WPS_OOB */ + + +static int hostapd_wps_probe_req_rx(void *ctx, const u8 *addr, + const u8 *ie, size_t ie_len) +{ + struct hostapd_data *hapd = ctx; struct wpabuf *wps_ie; - const u8 *end, *pos, *wps; + struct ieee802_11_elems elems; if (hapd->wps == NULL) - return; + return 0; - pos = ie; - end = ie + ie_len; - wps = NULL; - - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - return; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - WPA_GET_BE32(&pos[2]) == WPS_DEV_OUI_WFA) { - wps = pos; - break; - } - pos += 2 + pos[1]; + if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) { + wpa_printf(MSG_DEBUG, "WPS: Could not parse ProbeReq from " + MACSTR, MAC2STR(addr)); + return 0; } - if (wps == NULL) - return; /* No WPS IE in Probe Request */ + if (elems.ssid && elems.ssid_len > 0 && + (elems.ssid_len != hapd->conf->ssid.ssid_len || + os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) != + 0)) + return 0; /* Not for us */ - wps_ie = wpabuf_alloc(ie_len); + wps_ie = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA); if (wps_ie == NULL) - return; - - /* There may be multiple WPS IEs in the message, so need to concatenate - * their WPS Data fields */ - while (pos + 1 < end) { - if (pos + 2 + pos[1] > end) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - WPA_GET_BE32(&pos[2]) == WPS_DEV_OUI_WFA) - wpabuf_put_data(wps_ie, pos + 6, pos[1] - 4); - pos += 2 + pos[1]; - } + return 0; if (wpabuf_len(wps_ie) > 0) { wps_registrar_probe_req_rx(hapd->wps->registrar, addr, wps_ie); @@ -778,112 +832,13 @@ void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr, } wpabuf_free(wps_ie); + + return 0; } #ifdef CONFIG_WPS_UPNP -static struct wpabuf * -hostapd_rx_req_get_device_info(void *priv, struct upnp_wps_peer *peer) -{ - struct hostapd_data *hapd = priv; - struct wps_config cfg; - struct wps_data *wps; - enum wsc_op_code op_code; - struct wpabuf *m1; - - /* - * Request for DeviceInfo, i.e., M1 TLVs. This is a start of WPS - * registration over UPnP with the AP acting as an Enrollee. It should - * be noted that this is frequently used just to get the device data, - * i.e., there may not be any intent to actually complete the - * registration. - */ - - if (peer->wps) - wps_deinit(peer->wps); - - os_memset(&cfg, 0, sizeof(cfg)); - cfg.wps = hapd->wps; - cfg.pin = (u8 *) hapd->conf->ap_pin; - cfg.pin_len = os_strlen(hapd->conf->ap_pin); - wps = wps_init(&cfg); - if (wps == NULL) - return NULL; - - m1 = wps_get_msg(wps, &op_code); - if (m1 == NULL) { - wps_deinit(wps); - return NULL; - } - - peer->wps = wps; - - return m1; -} - - -static struct wpabuf * -hostapd_rx_req_put_message(void *priv, struct upnp_wps_peer *peer, - const struct wpabuf *msg) -{ - enum wps_process_res res; - enum wsc_op_code op_code; - - /* PutMessage: msg = InMessage, return OutMessage */ - res = wps_process_msg(peer->wps, WSC_UPnP, msg); - if (res == WPS_FAILURE) - return NULL; - return wps_get_msg(peer->wps, &op_code); -} - - -static struct wpabuf * -hostapd_rx_req_get_ap_settings(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return NULL; -} - - -static int hostapd_rx_req_set_ap_settings(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static int hostapd_rx_req_del_ap_settings(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static struct wpabuf * -hostapd_rx_req_get_sta_settings(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return NULL; -} - - -static int hostapd_rx_req_set_sta_settings(void *priv, - const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static int hostapd_rx_req_del_sta_settings(void *priv, - const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - static int hostapd_rx_req_put_wlan_response( void *priv, enum upnp_wps_wlanevent_type ev_type, const u8 *mac_addr, const struct wpabuf *msg, @@ -941,42 +896,6 @@ static int hostapd_rx_req_put_wlan_response( } -static int hostapd_rx_req_set_selected_registrar(void *priv, - const struct wpabuf *msg) -{ - struct hostapd_data *hapd = priv; - return wps_registrar_set_selected_registrar(hapd->wps->registrar, msg); -} - - -static int hostapd_rx_req_reboot_ap(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static int hostapd_rx_req_reset_ap(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static int hostapd_rx_req_reboot_sta(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - -static int hostapd_rx_req_reset_sta(void *priv, const struct wpabuf *msg) -{ - wpa_printf(MSG_DEBUG, "WPS UPnP: TODO %s", __func__); - return -1; -} - - static int hostapd_wps_upnp_init(struct hostapd_data *hapd, struct wps_context *wps) { @@ -988,21 +907,9 @@ static int hostapd_wps_upnp_init(struct hostapd_data *hapd, if (ctx == NULL) return -1; - ctx->rx_req_get_device_info = hostapd_rx_req_get_device_info; - ctx->rx_req_put_message = hostapd_rx_req_put_message; - ctx->rx_req_get_ap_settings = hostapd_rx_req_get_ap_settings; - ctx->rx_req_set_ap_settings = hostapd_rx_req_set_ap_settings; - ctx->rx_req_del_ap_settings = hostapd_rx_req_del_ap_settings; - ctx->rx_req_get_sta_settings = hostapd_rx_req_get_sta_settings; - ctx->rx_req_set_sta_settings = hostapd_rx_req_set_sta_settings; - ctx->rx_req_del_sta_settings = hostapd_rx_req_del_sta_settings; ctx->rx_req_put_wlan_response = hostapd_rx_req_put_wlan_response; - ctx->rx_req_set_selected_registrar = - hostapd_rx_req_set_selected_registrar; - ctx->rx_req_reboot_ap = hostapd_rx_req_reboot_ap; - ctx->rx_req_reset_ap = hostapd_rx_req_reset_ap; - ctx->rx_req_reboot_sta = hostapd_rx_req_reboot_sta; - ctx->rx_req_reset_sta = hostapd_rx_req_reset_sta; + if (hapd->conf->ap_pin) + ctx->ap_pin = os_strdup(hapd->conf->ap_pin); hapd->wps_upnp = upnp_wps_device_init(ctx, wps, hapd); if (hapd->wps_upnp == NULL) { @@ -1027,3 +934,87 @@ static void hostapd_wps_upnp_deinit(struct hostapd_data *hapd) } #endif /* CONFIG_WPS_UPNP */ + + +int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr, + char *buf, size_t buflen) +{ + if (hapd->wps == NULL) + return 0; + return wps_registrar_get_info(hapd->wps->registrar, addr, buf, buflen); +} + + +static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx) +{ + struct hostapd_data *hapd = eloop_data; + wpa_printf(MSG_DEBUG, "WPS: AP PIN timed out"); + hostapd_wps_ap_pin_disable(hapd); +} + + +static void hostapd_wps_ap_pin_enable(struct hostapd_data *hapd, int timeout) +{ + wpa_printf(MSG_DEBUG, "WPS: Enabling AP PIN (timeout=%d)", timeout); + hapd->ap_pin_failures = 0; + hapd->conf->ap_setup_locked = 0; + if (hapd->wps->ap_setup_locked) { + wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_UNLOCKED); + hapd->wps->ap_setup_locked = 0; + wps_registrar_update_ie(hapd->wps->registrar); + } + eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL); + if (timeout > 0) + eloop_register_timeout(timeout, 0, + hostapd_wps_ap_pin_timeout, hapd, NULL); +} + + +void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd) +{ + wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN"); + os_free(hapd->conf->ap_pin); + hapd->conf->ap_pin = NULL; +#ifdef CONFIG_WPS_UPNP + upnp_wps_set_ap_pin(hapd->wps_upnp, NULL); +#endif /* CONFIG_WPS_UPNP */ + eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL); +} + + +const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout) +{ + unsigned int pin; + char pin_txt[9]; + + pin = wps_generate_pin(); + os_snprintf(pin_txt, sizeof(pin_txt), "%u", pin); + os_free(hapd->conf->ap_pin); + hapd->conf->ap_pin = os_strdup(pin_txt); +#ifdef CONFIG_WPS_UPNP + upnp_wps_set_ap_pin(hapd->wps_upnp, pin_txt); +#endif /* CONFIG_WPS_UPNP */ + hostapd_wps_ap_pin_enable(hapd, timeout); + return hapd->conf->ap_pin; +} + + +const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd) +{ + return hapd->conf->ap_pin; +} + + +int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin, + int timeout) +{ + os_free(hapd->conf->ap_pin); + hapd->conf->ap_pin = os_strdup(pin); + if (hapd->conf->ap_pin == NULL) + return -1; +#ifdef CONFIG_WPS_UPNP + upnp_wps_set_ap_pin(hapd->wps_upnp, hapd->conf->ap_pin); +#endif /* CONFIG_WPS_UPNP */ + hostapd_wps_ap_pin_enable(hapd, timeout); + return 0; +} diff --git a/contrib/wpa/hostapd/wps_hostapd.h b/contrib/wpa/src/ap/wps_hostapd.h similarity index 52% rename from contrib/wpa/hostapd/wps_hostapd.h rename to contrib/wpa/src/ap/wps_hostapd.h index e949bee87ac6..e978a1cf668d 100644 --- a/contrib/wpa/hostapd/wps_hostapd.h +++ b/contrib/wpa/src/ap/wps_hostapd.h @@ -1,6 +1,6 @@ /* * hostapd / WPS integration - * Copyright (c) 2008, Jouni Malinen + * Copyright (c) 2008-2010, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -20,11 +20,19 @@ int hostapd_init_wps(struct hostapd_data *hapd, struct hostapd_bss_config *conf); void hostapd_deinit_wps(struct hostapd_data *hapd); +void hostapd_update_wps(struct hostapd_data *hapd); int hostapd_wps_add_pin(struct hostapd_data *hapd, const char *uuid, const char *pin, int timeout); int hostapd_wps_button_pushed(struct hostapd_data *hapd); -void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, const u8 *addr, - const u8 *ie, size_t ie_len); +int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type, + char *path, char *method, char *name); +int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr, + char *buf, size_t buflen); +void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd); +const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout); +const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd); +int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin, + int timeout); #else /* CONFIG_WPS */ @@ -38,11 +46,22 @@ static inline void hostapd_deinit_wps(struct hostapd_data *hapd) { } -static inline void hostapd_wps_probe_req_rx(struct hostapd_data *hapd, - const u8 *addr, - const u8 *ie, size_t ie_len) +static inline void hostapd_update_wps(struct hostapd_data *hapd) { } + +static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, + const u8 *addr, + char *buf, size_t buflen) +{ + return 0; +} + +static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd) +{ + return 0; +} + #endif /* CONFIG_WPS */ #endif /* WPS_HOSTAPD_H */ diff --git a/contrib/wpa/src/common/Makefile b/contrib/wpa/src/common/Makefile index cffba620da04..9c41962fd7e1 100644 --- a/contrib/wpa/src/common/Makefile +++ b/contrib/wpa/src/common/Makefile @@ -2,7 +2,6 @@ all: @echo Nothing to be made. clean: - for d in $(SUBDIRS); do make -C $$d clean; done rm -f *~ *.o *.d install: diff --git a/contrib/wpa/src/common/defs.h b/contrib/wpa/src/common/defs.h index 4930e73e75cc..173bbd1c9897 100644 --- a/contrib/wpa/src/common/defs.h +++ b/contrib/wpa/src/common/defs.h @@ -77,18 +77,44 @@ static inline int wpa_key_mgmt_sha256(int akm) #define WPA_AUTH_ALG_OPEN BIT(0) #define WPA_AUTH_ALG_SHARED BIT(1) #define WPA_AUTH_ALG_LEAP BIT(2) +#define WPA_AUTH_ALG_FT BIT(3) -typedef enum { WPA_ALG_NONE, WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP, - WPA_ALG_IGTK, WPA_ALG_PMK } wpa_alg; -typedef enum { CIPHER_NONE, CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, - CIPHER_WEP104 } wpa_cipher; -typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, - KEY_MGMT_802_1X_NO_WPA, KEY_MGMT_WPA_NONE, - KEY_MGMT_FT_802_1X, KEY_MGMT_FT_PSK, - KEY_MGMT_802_1X_SHA256, KEY_MGMT_PSK_SHA256, - KEY_MGMT_WPS -} wpa_key_mgmt; +enum wpa_alg { + WPA_ALG_NONE, + WPA_ALG_WEP, + WPA_ALG_TKIP, + WPA_ALG_CCMP, + WPA_ALG_IGTK, + WPA_ALG_PMK +}; + +/** + * enum wpa_cipher - Cipher suites + */ +enum wpa_cipher { + CIPHER_NONE, + CIPHER_WEP40, + CIPHER_TKIP, + CIPHER_CCMP, + CIPHER_WEP104 +}; + +/** + * enum wpa_key_mgmt - Key management suites + */ +enum wpa_key_mgmt { + KEY_MGMT_802_1X, + KEY_MGMT_PSK, + KEY_MGMT_NONE, + KEY_MGMT_802_1X_NO_WPA, + KEY_MGMT_WPA_NONE, + KEY_MGMT_FT_802_1X, + KEY_MGMT_FT_PSK, + KEY_MGMT_802_1X_SHA256, + KEY_MGMT_PSK_SHA256, + KEY_MGMT_WPS +}; /** * enum wpa_states - wpa_supplicant state @@ -100,7 +126,7 @@ typedef enum { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE, * wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used * to access the state variable. */ -typedef enum { +enum wpa_states { /** * WPA_DISCONNECTED - Disconnected state * @@ -128,6 +154,16 @@ typedef enum { */ WPA_SCANNING, + /** + * WPA_AUTHENTICATING - Trying to authenticate with a BSS/SSID + * + * This state is entered when wpa_supplicant has found a suitable BSS + * to authenticate with and the driver is configured to try to + * authenticate with this BSS. This state is used only with drivers + * that use wpa_supplicant as the SME. + */ + WPA_AUTHENTICATING, + /** * WPA_ASSOCIATING - Trying to associate with a BSS/SSID * @@ -186,7 +222,7 @@ typedef enum { * fully configured. */ WPA_COMPLETED -} wpa_states; +}; #define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0 #define MLME_SETPROTECTION_PROTECT_TYPE_RX 1 @@ -196,4 +232,24 @@ typedef enum { #define MLME_SETPROTECTION_KEY_TYPE_GROUP 0 #define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1 + +/** + * enum mfp_options - Management frame protection (IEEE 802.11w) options + */ +enum mfp_options { + NO_MGMT_FRAME_PROTECTION = 0, + MGMT_FRAME_PROTECTION_OPTIONAL = 1, + MGMT_FRAME_PROTECTION_REQUIRED = 2 +}; + +/** + * enum hostapd_hw_mode - Hardware mode + */ +enum hostapd_hw_mode { + HOSTAPD_MODE_IEEE80211B, + HOSTAPD_MODE_IEEE80211G, + HOSTAPD_MODE_IEEE80211A, + NUM_HOSTAPD_MODES +}; + #endif /* DEFS_H */ diff --git a/contrib/wpa/src/common/ieee802_11_common.c b/contrib/wpa/src/common/ieee802_11_common.c index 242f933b03fd..96ef5b65a176 100644 --- a/contrib/wpa/src/common/ieee802_11_common.c +++ b/contrib/wpa/src/common/ieee802_11_common.c @@ -1,6 +1,6 @@ /* * IEEE 802.11 Common routines - * Copyright (c) 2002-2008, Jouni Malinen + * Copyright (c) 2002-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -19,7 +19,7 @@ #include "ieee802_11_common.h" -static int ieee802_11_parse_vendor_specific(u8 *pos, size_t elen, +static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, struct ieee802_11_elems *elems, int show_errors) { @@ -131,12 +131,12 @@ static int ieee802_11_parse_vendor_specific(u8 *pos, size_t elen, * @show_errors: Whether to show parsing errors in debug log * Returns: Parsing result */ -ParseRes ieee802_11_parse_elems(u8 *start, size_t len, +ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors) { size_t left = len; - u8 *pos = start; + const u8 *pos = start; int unknown = 0; os_memset(elems, 0, sizeof(*elems)); @@ -257,3 +257,70 @@ ParseRes ieee802_11_parse_elems(u8 *start, size_t len, return unknown ? ParseUnknown : ParseOK; } + + +int ieee802_11_ie_count(const u8 *ies, size_t ies_len) +{ + int count = 0; + const u8 *pos, *end; + + if (ies == NULL) + return 0; + + pos = ies; + end = ies + ies_len; + + while (pos + 2 <= end) { + if (pos + 2 + pos[1] > end) + break; + count++; + pos += 2 + pos[1]; + } + + return count; +} + + +struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, + u32 oui_type) +{ + struct wpabuf *buf; + const u8 *end, *pos, *ie; + + pos = ies; + end = ies + ies_len; + ie = NULL; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + return NULL; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + WPA_GET_BE32(&pos[2]) == oui_type) { + ie = pos; + break; + } + pos += 2 + pos[1]; + } + + if (ie == NULL) + return NULL; /* No specified vendor IE found */ + + buf = wpabuf_alloc(ies_len); + if (buf == NULL) + return NULL; + + /* + * There may be multiple vendor IEs in the message, so need to + * concatenate their data fields. + */ + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + WPA_GET_BE32(&pos[2]) == oui_type) + wpabuf_put_data(buf, pos + 6, pos[1] - 4); + pos += 2 + pos[1]; + } + + return buf; +} diff --git a/contrib/wpa/src/common/ieee802_11_common.h b/contrib/wpa/src/common/ieee802_11_common.h index b7e497b6cc68..4a4f5a742cc5 100644 --- a/contrib/wpa/src/common/ieee802_11_common.h +++ b/contrib/wpa/src/common/ieee802_11_common.h @@ -1,6 +1,6 @@ /* * IEEE 802.11 Common routines - * Copyright (c) 2002-2008, Jouni Malinen + * Copyright (c) 2002-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -17,58 +17,62 @@ /* Parsed Information Elements */ struct ieee802_11_elems { - u8 *ssid; + const u8 *ssid; + const u8 *supp_rates; + const u8 *fh_params; + const u8 *ds_params; + const u8 *cf_params; + const u8 *tim; + const u8 *ibss_params; + const u8 *challenge; + const u8 *erp_info; + const u8 *ext_supp_rates; + const u8 *wpa_ie; + const u8 *rsn_ie; + const u8 *wmm; /* WMM Information or Parameter Element */ + const u8 *wmm_tspec; + const u8 *wps_ie; + const u8 *power_cap; + const u8 *supp_channels; + const u8 *mdie; + const u8 *ftie; + const u8 *timeout_int; + const u8 *ht_capabilities; + const u8 *ht_operation; + const u8 *vendor_ht_cap; + u8 ssid_len; - u8 *supp_rates; u8 supp_rates_len; - u8 *fh_params; u8 fh_params_len; - u8 *ds_params; u8 ds_params_len; - u8 *cf_params; u8 cf_params_len; - u8 *tim; u8 tim_len; - u8 *ibss_params; u8 ibss_params_len; - u8 *challenge; u8 challenge_len; - u8 *erp_info; u8 erp_info_len; - u8 *ext_supp_rates; u8 ext_supp_rates_len; - u8 *wpa_ie; u8 wpa_ie_len; - u8 *rsn_ie; u8 rsn_ie_len; - u8 *wmm; /* WMM Information or Parameter Element */ u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */ - u8 *wmm_tspec; u8 wmm_tspec_len; - u8 *wps_ie; u8 wps_ie_len; - u8 *power_cap; u8 power_cap_len; - u8 *supp_channels; u8 supp_channels_len; - u8 *mdie; u8 mdie_len; - u8 *ftie; u8 ftie_len; - u8 *timeout_int; u8 timeout_int_len; - u8 *ht_capabilities; u8 ht_capabilities_len; - u8 *ht_operation; u8 ht_operation_len; - u8 *vendor_ht_cap; u8 vendor_ht_cap_len; }; typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; -ParseRes ieee802_11_parse_elems(u8 *start, size_t len, +ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, struct ieee802_11_elems *elems, int show_errors); +int ieee802_11_ie_count(const u8 *ies, size_t ies_len); +struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, + u32 oui_type); #endif /* IEEE802_11_COMMON_H */ diff --git a/contrib/wpa/src/common/ieee802_11_defs.h b/contrib/wpa/src/common/ieee802_11_defs.h index d9e54a99ed50..4881e39a01a8 100644 --- a/contrib/wpa/src/common/ieee802_11_defs.h +++ b/contrib/wpa/src/common/ieee802_11_defs.h @@ -1,6 +1,6 @@ /* * IEEE 802.11 Frame type definitions - * Copyright (c) 2002-2007, Jouni Malinen + * Copyright (c) 2002-2009, Jouni Malinen * Copyright (c) 2007-2008 Intel Corporation * * This program is free software; you can redistribute it and/or modify @@ -116,9 +116,13 @@ #define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 #define WLAN_STATUS_ASSOC_DENIED_NO_ER_PBCC 26 #define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 27 +#define WLAN_STATUS_R0KH_UNREACHABLE 28 /* IEEE 802.11w */ #define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30 #define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 +#define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32 +#define WLAN_STATUS_REQUEST_DECLINED 37 +#define WLAN_STATUS_INVALID_PARAMETERS 38 /* IEEE 802.11i */ #define WLAN_STATUS_INVALID_IE 40 #define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41 @@ -233,6 +237,25 @@ #pragma pack(push, 1) #endif /* _MSC_VER */ +struct ieee80211_hdr { + le16 frame_control; + le16 duration_id; + u8 addr1[6]; + u8 addr2[6]; + u8 addr3[6]; + le16 seq_ctrl; + /* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame + */ +} STRUCT_PACKED; + +#define IEEE80211_DA_FROMDS addr1 +#define IEEE80211_BSSID_FROMDS addr2 +#define IEEE80211_SA_FROMDS addr3 + +#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr)) + +#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4)) + struct ieee80211_mgmt { le16 frame_control; le16 duration; @@ -337,45 +360,14 @@ struct ieee80211_mgmt { } u; } STRUCT_PACKED; -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ -#define ERP_INFO_NON_ERP_PRESENT BIT(0) -#define ERP_INFO_USE_PROTECTION BIT(1) -#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) - - -/* HT Capability element */ - -enum { - MAX_RX_AMPDU_FACTOR_8KB = 0, - MAX_RX_AMPDU_FACTOR_16KB, - MAX_RX_AMPDU_FACTOR_32KB, - MAX_RX_AMPDU_FACTOR_64KB -}; - -enum { - CALIBRATION_NOT_SUPPORTED = 0, - CALIBRATION_CANNOT_INIT, - CALIBRATION_CAN_INIT, - CALIBRATION_FULL_SUPPORT -}; - -enum { - MCS_FEEDBACK_NOT_PROVIDED = 0, - MCS_FEEDBACK_UNSOLICITED, - MCS_FEEDBACK_MRQ_RESPONSE -}; - - -struct ieee80211_ht_capability { - le16 capabilities_info; - u8 mac_ht_params_info; +struct ieee80211_ht_capabilities { + le16 ht_capabilities_info; + u8 a_mpdu_params; u8 supported_mcs_set[16]; - le16 extended_ht_capability_info; - le32 tx_BF_capability_info; - u8 antenna_selection_info; + le16 ht_extended_capabilities; + le32 tx_bf_capability_info; + u8 asel_capabilities; } STRUCT_PACKED; @@ -387,47 +379,13 @@ struct ieee80211_ht_operation { u8 basic_set[16]; } STRUCT_PACKED; -/* auxiliary bit manipulation macros FIXME: move it to common later... */ -#define SET_2BIT_U8(_ptr_, _shift_, _val_) \ - ((*(_ptr_) &= ~(3 << (_shift_))), \ - (*(_ptr_) |= (*(_ptr_) & (((u8)3) << (_shift_))) | \ - (((u8)(_val_) & 3) << _shift_))) +#ifdef _MSC_VER +#pragma pack(pop) +#endif /* _MSC_VER */ -#define GET_2BIT_U8(_var_, _shift_) \ - (((_var_) & (((u8)3) << (_shift_))) >> (_shift_)) - -#define SET_2BIT_LE16(_u16ptr_, _shift_, _val_) \ - ((*(_u16ptr_) &= ~(3 << (_shift_))), \ - (*(_u16ptr_) |= \ - (((*(_u16ptr_)) & (((u16)3) << ((u16)_shift_))) | \ - (((u16)(_val_) & (u16)3) << (u16)(_shift_))))) - -#define GET_2BIT_LE16(_var_, _shift_) \ - (((_var_) & (((u16)3) << (_shift_))) >> (_shift_)) - -#define SET_2BIT_LE32(_u32ptr_, _shift_, _val_) \ - ((*(_u32ptr_) &= ~(3 << (_shift_))), \ - (*(_u32ptr_) |= (((*(_u32ptr_)) & (((u32)3) << (_shift_))) | \ - (((u32)(_val_) & 3) << _shift_)))) - -#define GET_2BIT_LE32(_var_, _shift_) \ - (((_var_) & (((u32)3) << (_shift_))) >> (_shift_)) - -#define SET_3BIT_LE16(_u16ptr_, _shift_, _val_) \ - ((*(_u16ptr_) &= ~(7 << (_shift_))), \ - (*(_u16ptr_) |= (((*(_u16ptr_)) & (((u16)7) << (_shift_))) | \ - (((u16)(_val_) & 7) << _shift_)))) - -#define GET_3BIT_LE16(_var_, _shift_) \ - (((_var_) & (((u16)7) << (_shift_))) >> (_shift_)) - -#define SET_3BIT_LE32(_u32ptr_, _shift_, _val_) \ - ((*(_u32ptr_) &= ~(7 << (_shift_))), \ - (*(_u32ptr_) |= (((*(_u32ptr_)) & (((u32)7) << (_shift_))) | \ - (((u32)(_val_) & 7) << _shift_)))) - -#define GET_3BIT_LE32(_var_, _shift_) \ - (((_var_) & (((u32)7) << (_shift_))) >> (_shift_)) +#define ERP_INFO_NON_ERP_PRESENT BIT(0) +#define ERP_INFO_USE_PROTECTION BIT(1) +#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) #define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0)) @@ -452,9 +410,6 @@ struct ieee80211_ht_operation { #define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15)) -#define MAC_HT_PARAM_INFO_MAX_RX_AMPDU_FACTOR_OFFSET 0 -#define MAC_HT_PARAM_INFO_MAX_MPDU_DENSITY_OFFSET 2 - #define EXT_HT_CAP_INFO_PCO ((u16) BIT(0)) #define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET 1 #define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET 8 @@ -490,22 +445,6 @@ struct ieee80211_ht_operation { #define ASEL_CAPABILITY_RX_AS_CAP ((u8) BIT(5)) #define ASEL_CAPABILITY_TX_SOUND_PPDUS_CAP ((u8) BIT(6)) - -struct ht_cap_ie { - u8 id; - u8 length; - struct ieee80211_ht_capability data; -} STRUCT_PACKED; - - -#define REC_TRANS_CHNL_WIDTH_20 0 -#define REC_TRANS_CHNL_WIDTH_ANY 1 - -#define OP_MODE_PURE 0 -#define OP_MODE_MAY_BE_LEGACY_STAS 1 -#define OP_MODE_20MHZ_HT_STA_ASSOCED 2 -#define OP_MODE_MIXED 3 - #define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1)) #define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0)) #define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1)) @@ -514,6 +453,12 @@ struct ht_cap_ie { #define HT_INFO_HT_PARAM_CTRL_ACCESS_ONLY ((u8) BIT(4)) #define HT_INFO_HT_PARAM_SRV_INTERVAL_GRANULARITY ((u8) BIT(5)) + +#define OP_MODE_PURE 0 +#define OP_MODE_MAY_BE_LEGACY_STAS 1 +#define OP_MODE_20MHZ_HT_STA_ASSOCED 2 +#define OP_MODE_MIXED 3 + #define HT_INFO_OPERATION_MODE_OP_MODE_MASK \ ((le16) (0x0001 | 0x0002)) #define HT_INFO_OPERATION_MODE_OP_MODE_OFFSET 0 @@ -529,39 +474,10 @@ struct ht_cap_ie { #define HT_INFO_STBC_PARAM_PCO_PHASE ((u16) BIT(11)) -/* Secondary channel offset element */ -#define SECONDARY_CHANNEL_OFFSET_NONE 0 -#define SECONDARY_CHANNEL_OFFSET_ABOVE 1 -#define SECONDARY_CHANNEL_OFFSET_BELOW 3 -struct secondary_channel_offset_ie { - u8 id; - u8 length; - u8 secondary_offset_offset; -} STRUCT_PACKED; - - -/* body of Recommended Transmit Channel Width action frame */ -#define CHANNEL_WIDTH_20 0 -#define CHANNEL_WIDTH_ANY 1 -struct recommended_tx_channel_width_action { - u8 category; - u8 action; - u8 channel_width; -} STRUCT_PACKED; - -/* body of MIMO Power Save action frame */ -#define PWR_SAVE_MODE_STATIC 0 -#define PWR_SAVE_MODE_DYNAMIC 1 -struct mimo_pwr_save_action { - u8 category; - u8 action; - u8 enable; - u8 mode; -} STRUCT_PACKED; - - #define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs) * 00:50:F2 */ +#define WPA_IE_VENDOR_TYPE 0x0050f201 +#define WPS_IE_VENDOR_TYPE 0x0050f204 #define WMM_OUI_TYPE 2 #define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0 @@ -585,9 +501,107 @@ struct mimo_pwr_save_action { /* 2 - Reserved */ #define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3 +/* + * WMM Information Element (used in (Re)Association Request frames; may also be + * used in Beacon frames) + */ +struct wmm_information_element { + /* Element ID: 221 (0xdd); Length: 7 */ + /* required fields for WMM version 1 */ + u8 oui[3]; /* 00:50:f2 */ + u8 oui_type; /* 2 */ + u8 oui_subtype; /* 0 */ + u8 version; /* 1 for WMM version 1.0 */ + u8 qos_info; /* AP/STA specific QoS info */ + +} STRUCT_PACKED; + +#define WMM_AC_AIFSN_MASK 0x0f +#define WMM_AC_AIFNS_SHIFT 0 +#define WMM_AC_ACM 0x10 +#define WMM_AC_ACI_MASK 0x60 +#define WMM_AC_ACI_SHIFT 5 + +#define WMM_AC_ECWMIN_MASK 0x0f +#define WMM_AC_ECWMIN_SHIFT 0 +#define WMM_AC_ECWMAX_MASK 0xf0 +#define WMM_AC_ECWMAX_SHIFT 4 + +struct wmm_ac_parameter { + u8 aci_aifsn; /* AIFSN, ACM, ACI */ + u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */ + le16 txop_limit; +} STRUCT_PACKED; + +/* + * WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association + * Response frmaes) + */ +struct wmm_parameter_element { + /* Element ID: 221 (0xdd); Length: 24 */ + /* required fields for WMM version 1 */ + u8 oui[3]; /* 00:50:f2 */ + u8 oui_type; /* 2 */ + u8 oui_subtype; /* 1 */ + u8 version; /* 1 for WMM version 1.0 */ + u8 qos_info; /* AP/STA specif QoS info */ + u8 reserved; /* 0 */ + struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */ + +} STRUCT_PACKED; + +/* WMM TSPEC Element */ +struct wmm_tspec_element { + u8 eid; /* 221 = 0xdd */ + u8 length; /* 6 + 55 = 61 */ + u8 oui[3]; /* 00:50:f2 */ + u8 oui_type; /* 2 */ + u8 oui_subtype; /* 2 */ + u8 version; /* 1 */ + /* WMM TSPEC body (55 octets): */ + u8 ts_info[3]; + le16 nominal_msdu_size; + le16 maximum_msdu_size; + le32 minimum_service_interval; + le32 maximum_service_interval; + le32 inactivity_interval; + le32 suspension_interval; + le32 service_start_time; + le32 minimum_data_rate; + le32 mean_data_rate; + le32 peak_data_rate; + le32 maximum_burst_size; + le32 delay_bound; + le32 minimum_phy_rate; + le16 surplus_bandwidth_allowance; + le16 medium_time; +} STRUCT_PACKED; + + +/* Access Categories / ACI to AC coding */ +enum { + WMM_AC_BE = 0 /* Best Effort */, + WMM_AC_BK = 1 /* Background */, + WMM_AC_VI = 2 /* Video */, + WMM_AC_VO = 3 /* Voice */ +}; + #define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */ #define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */ +/* cipher suite selectors */ +#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 +#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 +#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 +/* reserved: 0x000FAC03 */ +#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 +#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 +#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 + +/* AKM suite selectors */ +#define WLAN_AKM_SUITE_8021X 0x000FAC01 +#define WLAN_AKM_SUITE_PSK 0x000FAC02 + #endif /* IEEE802_11_DEFS_H */ diff --git a/contrib/wpa/src/common/nl80211_copy.h b/contrib/wpa/src/common/nl80211_copy.h deleted file mode 100644 index 45db17f81aa3..000000000000 --- a/contrib/wpa/src/common/nl80211_copy.h +++ /dev/null @@ -1,1434 +0,0 @@ -#ifndef __LINUX_NL80211_H -#define __LINUX_NL80211_H -/* - * 802.11 netlink interface public header - * - * Copyright 2006, 2007, 2008 Johannes Berg - * Copyright 2008 Michael Wu - * Copyright 2008 Luis Carlos Cobo - * Copyright 2008 Michael Buesch - * Copyright 2008, 2009 Luis R. Rodriguez - * Copyright 2008 Jouni Malinen - * Copyright 2008 Colin McCabe - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include - -/** - * DOC: Station handling - * - * Stations are added per interface, but a special case exists with VLAN - * interfaces. When a station is bound to an AP interface, it may be moved - * into a VLAN identified by a VLAN interface index (%NL80211_ATTR_STA_VLAN). - * The station is still assumed to belong to the AP interface it was added - * to. - * - * TODO: need more info? - */ - -/** - * enum nl80211_commands - supported nl80211 commands - * - * @NL80211_CMD_UNSPEC: unspecified command to catch errors - * - * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request - * to get a list of all present wiphys. - * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or - * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, - * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, - * %NL80211_ATTR_WIPHY_CHANNEL_TYPE, %NL80211_ATTR_WIPHY_RETRY_SHORT, - * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, - * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. - * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request - * or rename notification. Has attributes %NL80211_ATTR_WIPHY and - * %NL80211_ATTR_WIPHY_NAME. - * @NL80211_CMD_DEL_WIPHY: Wiphy deleted. Has attributes - * %NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME. - * - * @NL80211_CMD_GET_INTERFACE: Request an interface's configuration; - * either a dump request on a %NL80211_ATTR_WIPHY or a specific get - * on an %NL80211_ATTR_IFINDEX is supported. - * @NL80211_CMD_SET_INTERFACE: Set type of a virtual interface, requires - * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE. - * @NL80211_CMD_NEW_INTERFACE: Newly created virtual interface or response - * to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX, - * %NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also - * be sent from userspace to request creation of a new virtual interface, - * then requires attributes %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFTYPE and - * %NL80211_ATTR_IFNAME. - * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes - * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from - * userspace to request deletion of a virtual interface, then requires - * attribute %NL80211_ATTR_IFINDEX. - * - * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified - * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. - * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, - * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. - * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, - * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER, - * and %NL80211_ATTR_KEY_SEQ attributes. - * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX - * or %NL80211_ATTR_MAC. - * - * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a - * %NL80222_CMD_NEW_BEACON message) - * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface - * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD, - * %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes. - * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface, - * parameters are like for %NL80211_CMD_SET_BEACON. - * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it - * - * @NL80211_CMD_GET_STATION: Get station attributes for station identified by - * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_SET_STATION: Set station attributes for station identified by - * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the - * the interface identified by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC - * or, if no MAC address given, all stations, on the interface identified - * by %NL80211_ATTR_IFINDEX. - * - * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to - * destination %NL80211_ATTR_MAC on the interface identified by - * %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to - * destination %NL80211_ATTR_MAC on the interface identified by - * %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the - * the interface identified by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC - * or, if no MAC address given, all mesh paths, on the interface identified - * by %NL80211_ATTR_IFINDEX. - * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by - * %NL80211_ATTR_IFINDEX. - * - * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set - * regulatory domain. - * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command - * after being queried by the kernel. CRDA replies by sending a regulatory - * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our - * current alpha2 if it found a match. It also provides - * NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each - * regulatory rule is a nested set of attributes given by - * %NL80211_ATTR_REG_RULE_FREQ_[START|END] and - * %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by - * %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and - * %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP. - * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain - * to the the specified ISO/IEC 3166-1 alpha2 country code. The core will - * store this as a valid request and then query userspace for it. - * - * @NL80211_CMD_GET_MESH_PARAMS: Get mesh networking properties for the - * interface identified by %NL80211_ATTR_IFINDEX - * - * @NL80211_CMD_SET_MESH_PARAMS: Set mesh networking properties for the - * interface identified by %NL80211_ATTR_IFINDEX - * - * @NL80211_CMD_SET_MGMT_EXTRA_IE: Set extra IEs for management frames. The - * interface is identified with %NL80211_ATTR_IFINDEX and the management - * frame subtype with %NL80211_ATTR_MGMT_SUBTYPE. The extra IE data to be - * added to the end of the specified management frame is specified with - * %NL80211_ATTR_IE. If the command succeeds, the requested data will be - * added to all specified management frames generated by - * kernel/firmware/driver. - * Note: This command has been removed and it is only reserved at this - * point to avoid re-using existing command number. The functionality this - * command was planned for has been provided with cleaner design with the - * option to specify additional IEs in NL80211_CMD_TRIGGER_SCAN, - * NL80211_CMD_AUTHENTICATE, NL80211_CMD_ASSOCIATE, - * NL80211_CMD_DEAUTHENTICATE, and NL80211_CMD_DISASSOCIATE. - * - * @NL80211_CMD_GET_SCAN: get scan results - * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters - * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to - * NL80211_CMD_GET_SCAN and on the "scan" multicast group) - * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, - * partial scan results may be available - * - * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation - * or noise level - * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to - * NL80211_CMD_GET_SURVEY and on the "scan" multicast group) - * - * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain - * has been changed and provides details of the request information - * that caused the change such as who initiated the regulatory request - * (%NL80211_ATTR_REG_INITIATOR), the wiphy_idx - * (%NL80211_ATTR_REG_ALPHA2) on which the request was made from if - * the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or - * %NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain - * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is - * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on - * to (%NL80211_ATTR_REG_ALPHA2). - * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon - * has been found while world roaming thus enabling active scan or - * any mode of operation that initiates TX (beacons) on a channel - * where we would not have been able to do either before. As an example - * if you are world roaming (regulatory domain set to world or if your - * driver is using a custom world roaming regulatory domain) and while - * doing a passive scan on the 5 GHz band you find an AP there (if not - * on a DFS channel) you will now be able to actively scan for that AP - * or use AP mode on your card on that same channel. Note that this will - * never be used for channels 1-11 on the 2 GHz band as they are always - * enabled world wide. This beacon hint is only sent if your device had - * either disabled active scanning or beaconing on a channel. We send to - * userspace the wiphy on which we removed a restriction from - * (%NL80211_ATTR_WIPHY) and the channel on which this occurred - * before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER) - * the beacon hint was processed. - * - * @NL80211_CMD_AUTHENTICATE: authentication request and notification. - * This command is used both as a command (request to authenticate) and - * as an event on the "mlme" multicast group indicating completion of the - * authentication process. - * When used as a command, %NL80211_ATTR_IFINDEX is used to identify the - * interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and - * BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify - * the SSID (mainly for association, but is included in authentication - * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used - * to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE - * is used to specify the authentication type. %NL80211_ATTR_IE is used to - * define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs) - * to be added to the frame. - * When used as an event, this reports reception of an Authentication - * frame in station and IBSS modes when the local MLME processed the - * frame, i.e., it was for the local STA and was received in correct - * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the - * MLME SAP interface (kernel providing MLME, userspace SME). The - * included %NL80211_ATTR_FRAME attribute contains the management frame - * (including both the header and frame body, but not FCS). This event is - * also used to indicate if the authentication attempt timed out. In that - * case the %NL80211_ATTR_FRAME attribute is replaced with a - * %NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which - * pending authentication timed out). - * @NL80211_CMD_ASSOCIATE: association request and notification; like - * NL80211_CMD_AUTHENTICATE but for Association and Reassociation - * (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request, - * MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives). - * @NL80211_CMD_DEAUTHENTICATE: deauthentication request and notification; like - * NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to - * MLME-DEAUTHENTICATION.request and MLME-DEAUTHENTICATE.indication - * primitives). - * @NL80211_CMD_DISASSOCIATE: disassociation request and notification; like - * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to - * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives). - * - * @NL80211_CMD_MICHAEL_MIC_FAILURE: notification of a locally detected Michael - * MIC (part of TKIP) failure; sent on the "mlme" multicast group; the - * event includes %NL80211_ATTR_MAC to describe the source MAC address of - * the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key - * type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and - * %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this - * event matches with MLME-MICHAELMICFAILURE.indication() primitive - * - * @NL80211_CMD_JOIN_IBSS: Join a new IBSS -- given at least an SSID and a - * FREQ attribute (for the initial frequency if no peer can be found) - * and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those - * should be fixed rather than automatically determined. Can only be - * executed on a network interface that is UP, and fixed BSSID/FREQ - * may be rejected. Another optional parameter is the beacon interval, - * given in the %NL80211_ATTR_BEACON_INTERVAL attribute, which if not - * given defaults to 100 TU (102.4ms). - * @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is - * determined by the network interface. - * - * @NL80211_CMD_TESTMODE: testmode command, takes a wiphy (or ifindex) attribute - * to identify the device, and the TESTDATA blob attribute to pass through - * to the driver. - * - * @NL80211_CMD_CONNECT: connection request and notification; this command - * requests to connect to a specified network but without separating - * auth and assoc steps. For this, you need to specify the SSID in a - * %NL80211_ATTR_SSID attribute, and can optionally specify the association - * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_MAC, - * %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_CONTROL_PORT. - * It is also sent as an event, with the BSSID and response IEs when the - * connection is established or failed to be established. This can be - * determined by the STATUS_CODE attribute. - * @NL80211_CMD_ROAM: request that the card roam (currently not implemented), - * sent as an event when the card/driver roamed by itself. - * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify - * userspace that a connection was dropped by the AP or due to other - * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and - * %NL80211_ATTR_REASON_CODE attributes are used. - * - * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices - * associated with this wiphy must be down and will follow. - * - * @NL80211_CMD_MAX: highest used command number - * @__NL80211_CMD_AFTER_LAST: internal use - */ -enum nl80211_commands { -/* don't change the order or add anything inbetween, this is ABI! */ - NL80211_CMD_UNSPEC, - - NL80211_CMD_GET_WIPHY, /* can dump */ - NL80211_CMD_SET_WIPHY, - NL80211_CMD_NEW_WIPHY, - NL80211_CMD_DEL_WIPHY, - - NL80211_CMD_GET_INTERFACE, /* can dump */ - NL80211_CMD_SET_INTERFACE, - NL80211_CMD_NEW_INTERFACE, - NL80211_CMD_DEL_INTERFACE, - - NL80211_CMD_GET_KEY, - NL80211_CMD_SET_KEY, - NL80211_CMD_NEW_KEY, - NL80211_CMD_DEL_KEY, - - NL80211_CMD_GET_BEACON, - NL80211_CMD_SET_BEACON, - NL80211_CMD_NEW_BEACON, - NL80211_CMD_DEL_BEACON, - - NL80211_CMD_GET_STATION, - NL80211_CMD_SET_STATION, - NL80211_CMD_NEW_STATION, - NL80211_CMD_DEL_STATION, - - NL80211_CMD_GET_MPATH, - NL80211_CMD_SET_MPATH, - NL80211_CMD_NEW_MPATH, - NL80211_CMD_DEL_MPATH, - - NL80211_CMD_SET_BSS, - - NL80211_CMD_SET_REG, - NL80211_CMD_REQ_SET_REG, - - NL80211_CMD_GET_MESH_PARAMS, - NL80211_CMD_SET_MESH_PARAMS, - - NL80211_CMD_SET_MGMT_EXTRA_IE /* reserved; not used */, - - NL80211_CMD_GET_REG, - - NL80211_CMD_GET_SCAN, - NL80211_CMD_TRIGGER_SCAN, - NL80211_CMD_NEW_SCAN_RESULTS, - NL80211_CMD_SCAN_ABORTED, - - NL80211_CMD_REG_CHANGE, - - NL80211_CMD_AUTHENTICATE, - NL80211_CMD_ASSOCIATE, - NL80211_CMD_DEAUTHENTICATE, - NL80211_CMD_DISASSOCIATE, - - NL80211_CMD_MICHAEL_MIC_FAILURE, - - NL80211_CMD_REG_BEACON_HINT, - - NL80211_CMD_JOIN_IBSS, - NL80211_CMD_LEAVE_IBSS, - - NL80211_CMD_TESTMODE, - - NL80211_CMD_CONNECT, - NL80211_CMD_ROAM, - NL80211_CMD_DISCONNECT, - - NL80211_CMD_SET_WIPHY_NETNS, - - NL80211_CMD_GET_SURVEY, - NL80211_CMD_NEW_SURVEY_RESULTS, - - /* add new commands above here */ - - /* used to define NL80211_CMD_MAX below */ - __NL80211_CMD_AFTER_LAST, - NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1 -}; - -/* - * Allow user space programs to use #ifdef on new commands by defining them - * here - */ -#define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS -#define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE -#define NL80211_CMD_REG_CHANGE NL80211_CMD_REG_CHANGE -#define NL80211_CMD_AUTHENTICATE NL80211_CMD_AUTHENTICATE -#define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE -#define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE -#define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE -#define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT - -/** - * enum nl80211_attrs - nl80211 netlink attributes - * - * @NL80211_ATTR_UNSPEC: unspecified attribute to catch errors - * - * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf. - * /sys/class/ieee80211/ /index - * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) - * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters - * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz - * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ - * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included): - * NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including - * this attribute) - * NL80211_CHAN_HT20 = HT20 only - * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel - * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel - * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is - * less than or equal to the RTS threshold; allowed range: 1..255; - * dot11ShortRetryLimit; u8 - * @NL80211_ATTR_WIPHY_RETRY_LONG: TX retry limit for frames whose length is - * greater than the RTS threshold; allowed range: 1..255; - * dot11ShortLongLimit; u8 - * @NL80211_ATTR_WIPHY_FRAG_THRESHOLD: fragmentation threshold, i.e., maximum - * length in octets for frames; allowed range: 256..8000, disable - * fragmentation with (u32)-1; dot11FragmentationThreshold; u32 - * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length - * larger than or equal to this use RTS/CTS handshake); allowed range: - * 0..65536, disable with (u32)-1; dot11RTSThreshold; u32 - * - * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on - * @NL80211_ATTR_IFNAME: network interface name - * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype - * - * @NL80211_ATTR_MAC: MAC address (various uses) - * - * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of - * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC - * keys - * @NL80211_ATTR_KEY_IDX: key ID (u8, 0-3) - * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 - * section 7.3.2.25.1, e.g. 0x000FAC04) - * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and - * CCMP keys, each six bytes in little endian - * - * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU - * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing - * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE - * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE - * - * @NL80211_ATTR_STA_AID: Association ID for the station (u16) - * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of - * &enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2) - * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by - * IEEE 802.11 7.3.1.6 (u16). - * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported - * rates as defined by IEEE 802.11 7.3.2.2 but without the length - * restriction (at most %NL80211_MAX_SUPP_RATES). - * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station - * to, or the AP interface the station was originally added to to. - * @NL80211_ATTR_STA_INFO: information about a station, part of station info - * given for %NL80211_CMD_GET_STATION, nested attribute containing - * info as possible, see &enum nl80211_sta_info. - * - * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands, - * consisting of a nested array. - * - * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). - * @NL80211_ATTR_PLINK_ACTION: action to perform on the mesh peer link. - * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. - * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path - * info given for %NL80211_CMD_GET_MPATH, nested attribute described at - * &enum nl80211_mpath_info. - * - * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of - * &enum nl80211_mntr_flags. - * - * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the - * current regulatory domain should be set to or is already set to. - * For example, 'CR', for Costa Rica. This attribute is used by the kernel - * to query the CRDA to retrieve one regulatory domain. This attribute can - * also be used by userspace to query the kernel for the currently set - * regulatory domain. We chose an alpha2 as that is also used by the - * IEEE-802.11d country information element to identify a country. - * Users can also simply ask the wireless core to set regulatory domain - * to a specific alpha2. - * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory - * rules. - * - * @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1) - * @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled - * (u8, 0 or 1) - * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled - * (u8, 0 or 1) - * @NL80211_ATTR_BSS_BASIC_RATES: basic rates, array of basic - * rates in format defined by IEEE 802.11 7.3.2.2 but without the length - * restriction (at most %NL80211_MAX_SUPP_RATES). - * - * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from - * association request when used with NL80211_CMD_NEW_STATION) - * - * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all - * supported interface types, each a flag attribute with the number - * of the interface mode. - * - * @NL80211_ATTR_MGMT_SUBTYPE: Management frame subtype for - * %NL80211_CMD_SET_MGMT_EXTRA_IE. - * - * @NL80211_ATTR_IE: Information element(s) data (used, e.g., with - * %NL80211_CMD_SET_MGMT_EXTRA_IE). - * - * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with - * a single scan request, a wiphy attribute. - * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements - * that can be added to a scan request - * - * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) - * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive - * scanning and include a zero-length SSID (wildcard) for wildcard scan - * @NL80211_ATTR_BSS: scan result BSS - * - * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain - * currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_* - * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently - * set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*) - * - * @NL80211_ATTR_SUPPORTED_COMMANDS: wiphy attribute that specifies - * an array of command numbers (i.e. a mapping index to command number) - * that the driver for the given wiphy supports. - * - * @NL80211_ATTR_FRAME: frame data (binary attribute), including frame header - * and body, but not FCS; used, e.g., with NL80211_CMD_AUTHENTICATE and - * NL80211_CMD_ASSOCIATE events - * @NL80211_ATTR_SSID: SSID (binary attribute, 0..32 octets) - * @NL80211_ATTR_AUTH_TYPE: AuthenticationType, see &enum nl80211_auth_type, - * represented as a u32 - * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and - * %NL80211_CMD_DISASSOCIATE, u16 - * - * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as - * a u32 - * - * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change - * due to considerations from a beacon hint. This attribute reflects - * the state of the channel _before_ the beacon hint processing. This - * attributes consists of a nested attribute containing - * NL80211_FREQUENCY_ATTR_* - * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change - * due to considerations from a beacon hint. This attribute reflects - * the state of the channel _after_ the beacon hint processing. This - * attributes consists of a nested attribute containing - * NL80211_FREQUENCY_ATTR_* - * - * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported - * cipher suites - * - * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look - * for other networks on different channels - * - * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this - * is used, e.g., with %NL80211_CMD_AUTHENTICATE event - * - * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is - * used for the association (&enum nl80211_mfp, represented as a u32); - * this attribute can be used - * with %NL80211_CMD_ASSOCIATE request - * - * @NL80211_ATTR_STA_FLAGS2: Attribute containing a - * &struct nl80211_sta_flag_update. - * - * @NL80211_ATTR_CONTROL_PORT: A flag indicating whether user space controls - * IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in - * station mode. If the flag is included in %NL80211_CMD_ASSOCIATE - * request, the driver will assume that the port is unauthorized until - * authorized by user space. Otherwise, port is marked authorized by - * default in station mode. - * - * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver. - * We recommend using nested, driver-specific attributes within this. - * - * @NL80211_ATTR_DISCONNECTED_BY_AP: A flag indicating that the DISCONNECT - * event was due to the AP disconnecting the station, and not due to - * a local disconnect request. - * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT - * event (u16) - * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating - * that protected APs should be used. - * - * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT and ASSOCIATE to - * indicate which unicast key ciphers will be used with the connection - * (an array of u32). - * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT and ASSOCIATE to indicate - * which group key cipher will be used with the connection (a u32). - * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT and ASSOCIATE to indicate - * which WPA version(s) the AP we want to associate with is using - * (a u32 with flags from &enum nl80211_wpa_versions). - * @NL80211_ATTR_AKM_SUITES: Used with CONNECT and ASSOCIATE to indicate - * which key management algorithm(s) to use (an array of u32). - * - * @NL80211_ATTR_REQ_IE: (Re)association request information elements as - * sent out by the card, for ROAM and successful CONNECT events. - * @NL80211_ATTR_RESP_IE: (Re)association response information elements as - * sent by peer, for ROAM and successful CONNECT events. - * - * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE - * commands to specify using a reassociate frame - * - * @NL80211_ATTR_KEY: key information in a nested attribute with - * %NL80211_KEY_* sub-attributes - * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect() - * and join_ibss(), key information is in a nested attribute each - * with %NL80211_KEY_* sub-attributes - * - * @NL80211_ATTR_PID: Process ID of a network namespace. - * - * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for - * dumps. This number increases whenever the object list being - * dumped changes, and as such userspace can verify that it has - * obtained a complete and consistent snapshot by verifying that - * all dump messages contain the same generation number. If it - * changed then the list changed and the dump should be repeated - * completely from scratch. - * - * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface - * - * @NL80211_ATTR_SURVEY_INFO: survey information about a channel, part of - * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute - * containing info as possible, see &enum survey_info. - * - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use - */ -enum nl80211_attrs { -/* don't change the order or add anything inbetween, this is ABI! */ - NL80211_ATTR_UNSPEC, - - NL80211_ATTR_WIPHY, - NL80211_ATTR_WIPHY_NAME, - - NL80211_ATTR_IFINDEX, - NL80211_ATTR_IFNAME, - NL80211_ATTR_IFTYPE, - - NL80211_ATTR_MAC, - - NL80211_ATTR_KEY_DATA, - NL80211_ATTR_KEY_IDX, - NL80211_ATTR_KEY_CIPHER, - NL80211_ATTR_KEY_SEQ, - NL80211_ATTR_KEY_DEFAULT, - - NL80211_ATTR_BEACON_INTERVAL, - NL80211_ATTR_DTIM_PERIOD, - NL80211_ATTR_BEACON_HEAD, - NL80211_ATTR_BEACON_TAIL, - - NL80211_ATTR_STA_AID, - NL80211_ATTR_STA_FLAGS, - NL80211_ATTR_STA_LISTEN_INTERVAL, - NL80211_ATTR_STA_SUPPORTED_RATES, - NL80211_ATTR_STA_VLAN, - NL80211_ATTR_STA_INFO, - - NL80211_ATTR_WIPHY_BANDS, - - NL80211_ATTR_MNTR_FLAGS, - - NL80211_ATTR_MESH_ID, - NL80211_ATTR_STA_PLINK_ACTION, - NL80211_ATTR_MPATH_NEXT_HOP, - NL80211_ATTR_MPATH_INFO, - - NL80211_ATTR_BSS_CTS_PROT, - NL80211_ATTR_BSS_SHORT_PREAMBLE, - NL80211_ATTR_BSS_SHORT_SLOT_TIME, - - NL80211_ATTR_HT_CAPABILITY, - - NL80211_ATTR_SUPPORTED_IFTYPES, - - NL80211_ATTR_REG_ALPHA2, - NL80211_ATTR_REG_RULES, - - NL80211_ATTR_MESH_PARAMS, - - NL80211_ATTR_BSS_BASIC_RATES, - - NL80211_ATTR_WIPHY_TXQ_PARAMS, - NL80211_ATTR_WIPHY_FREQ, - NL80211_ATTR_WIPHY_CHANNEL_TYPE, - - NL80211_ATTR_KEY_DEFAULT_MGMT, - - NL80211_ATTR_MGMT_SUBTYPE, - NL80211_ATTR_IE, - - NL80211_ATTR_MAX_NUM_SCAN_SSIDS, - - NL80211_ATTR_SCAN_FREQUENCIES, - NL80211_ATTR_SCAN_SSIDS, - NL80211_ATTR_GENERATION, /* replaces old SCAN_GENERATION */ - NL80211_ATTR_BSS, - - NL80211_ATTR_REG_INITIATOR, - NL80211_ATTR_REG_TYPE, - - NL80211_ATTR_SUPPORTED_COMMANDS, - - NL80211_ATTR_FRAME, - NL80211_ATTR_SSID, - NL80211_ATTR_AUTH_TYPE, - NL80211_ATTR_REASON_CODE, - - NL80211_ATTR_KEY_TYPE, - - NL80211_ATTR_MAX_SCAN_IE_LEN, - NL80211_ATTR_CIPHER_SUITES, - - NL80211_ATTR_FREQ_BEFORE, - NL80211_ATTR_FREQ_AFTER, - - NL80211_ATTR_FREQ_FIXED, - - - NL80211_ATTR_WIPHY_RETRY_SHORT, - NL80211_ATTR_WIPHY_RETRY_LONG, - NL80211_ATTR_WIPHY_FRAG_THRESHOLD, - NL80211_ATTR_WIPHY_RTS_THRESHOLD, - - NL80211_ATTR_TIMED_OUT, - - NL80211_ATTR_USE_MFP, - - NL80211_ATTR_STA_FLAGS2, - - NL80211_ATTR_CONTROL_PORT, - - NL80211_ATTR_TESTDATA, - - NL80211_ATTR_PRIVACY, - - NL80211_ATTR_DISCONNECTED_BY_AP, - NL80211_ATTR_STATUS_CODE, - - NL80211_ATTR_CIPHER_SUITES_PAIRWISE, - NL80211_ATTR_CIPHER_SUITE_GROUP, - NL80211_ATTR_WPA_VERSIONS, - NL80211_ATTR_AKM_SUITES, - - NL80211_ATTR_REQ_IE, - NL80211_ATTR_RESP_IE, - - NL80211_ATTR_PREV_BSSID, - - NL80211_ATTR_KEY, - NL80211_ATTR_KEYS, - - NL80211_ATTR_PID, - - NL80211_ATTR_4ADDR, - - NL80211_ATTR_SURVEY_INFO, - - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, - NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 -}; - -/* source-level API compatibility */ -#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION - -/* - * Allow user space programs to use #ifdef on new attributes by defining them - * here - */ -#define NL80211_CMD_CONNECT NL80211_CMD_CONNECT -#define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY -#define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES -#define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS -#define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ -#define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE -#define NL80211_ATTR_MGMT_SUBTYPE NL80211_ATTR_MGMT_SUBTYPE -#define NL80211_ATTR_IE NL80211_ATTR_IE -#define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR -#define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE -#define NL80211_ATTR_FRAME NL80211_ATTR_FRAME -#define NL80211_ATTR_SSID NL80211_ATTR_SSID -#define NL80211_ATTR_AUTH_TYPE NL80211_ATTR_AUTH_TYPE -#define NL80211_ATTR_REASON_CODE NL80211_ATTR_REASON_CODE -#define NL80211_ATTR_CIPHER_SUITES_PAIRWISE NL80211_ATTR_CIPHER_SUITES_PAIRWISE -#define NL80211_ATTR_CIPHER_SUITE_GROUP NL80211_ATTR_CIPHER_SUITE_GROUP -#define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS -#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES -#define NL80211_ATTR_KEY NL80211_ATTR_KEY -#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS - -#define NL80211_MAX_SUPP_RATES 32 -#define NL80211_MAX_SUPP_REG_RULES 32 -#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 -#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 -#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 -#define NL80211_HT_CAPABILITY_LEN 26 - -#define NL80211_MAX_NR_CIPHER_SUITES 5 -#define NL80211_MAX_NR_AKM_SUITES 2 - -/** - * enum nl80211_iftype - (virtual) interface types - * - * @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides - * @NL80211_IFTYPE_ADHOC: independent BSS member - * @NL80211_IFTYPE_STATION: managed BSS member - * @NL80211_IFTYPE_AP: access point - * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points - * @NL80211_IFTYPE_WDS: wireless distribution interface - * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames - * @NL80211_IFTYPE_MESH_POINT: mesh point - * @NL80211_IFTYPE_MAX: highest interface type number currently defined - * @__NL80211_IFTYPE_AFTER_LAST: internal use - * - * These values are used with the %NL80211_ATTR_IFTYPE - * to set the type of an interface. - * - */ -enum nl80211_iftype { - NL80211_IFTYPE_UNSPECIFIED, - NL80211_IFTYPE_ADHOC, - NL80211_IFTYPE_STATION, - NL80211_IFTYPE_AP, - NL80211_IFTYPE_AP_VLAN, - NL80211_IFTYPE_WDS, - NL80211_IFTYPE_MONITOR, - NL80211_IFTYPE_MESH_POINT, - - /* keep last */ - __NL80211_IFTYPE_AFTER_LAST, - NL80211_IFTYPE_MAX = __NL80211_IFTYPE_AFTER_LAST - 1 -}; - -/** - * enum nl80211_sta_flags - station flags - * - * Station flags. When a station is added to an AP interface, it is - * assumed to be already associated (and hence authenticated.) - * - * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X) - * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames - * with short barker preamble - * @NL80211_STA_FLAG_WME: station is WME/QoS capable - * @NL80211_STA_FLAG_MFP: station uses management frame protection - */ -enum nl80211_sta_flags { - __NL80211_STA_FLAG_INVALID, - NL80211_STA_FLAG_AUTHORIZED, - NL80211_STA_FLAG_SHORT_PREAMBLE, - NL80211_STA_FLAG_WME, - NL80211_STA_FLAG_MFP, - - /* keep last */ - __NL80211_STA_FLAG_AFTER_LAST, - NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 -}; - -/** - * struct nl80211_sta_flag_update - station flags mask/set - * @mask: mask of station flags to set - * @set: which values to set them to - * - * Both mask and set contain bits as per &enum nl80211_sta_flags. - */ -struct nl80211_sta_flag_update { - __u32 mask; - __u32 set; -} __attribute__((packed)); - -/** - * enum nl80211_rate_info - bitrate information - * - * These attribute types are used with %NL80211_STA_INFO_TXRATE - * when getting information about the bitrate of a station. - * - * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved - * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) - * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) - * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate - * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval - * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined - * @__NL80211_RATE_INFO_AFTER_LAST: internal use - */ -enum nl80211_rate_info { - __NL80211_RATE_INFO_INVALID, - NL80211_RATE_INFO_BITRATE, - NL80211_RATE_INFO_MCS, - NL80211_RATE_INFO_40_MHZ_WIDTH, - NL80211_RATE_INFO_SHORT_GI, - - /* keep last */ - __NL80211_RATE_INFO_AFTER_LAST, - NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1 -}; - -/** - * enum nl80211_sta_info - station information - * - * These attribute types are used with %NL80211_ATTR_STA_INFO - * when getting information about a station. - * - * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved - * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs) - * @NL80211_STA_INFO_RX_BYTES: total received bytes (u32, from this station) - * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) - * @__NL80211_STA_INFO_AFTER_LAST: internal - * @NL80211_STA_INFO_MAX: highest possible station info attribute - * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) - * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute - * containing info as possible, see &enum nl80211_sta_info_txrate. - * @NL80211_STA_INFO_RX_PACKETS: total received packet (u32, from this station) - * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (u32, to this - * station) - */ -enum nl80211_sta_info { - __NL80211_STA_INFO_INVALID, - NL80211_STA_INFO_INACTIVE_TIME, - NL80211_STA_INFO_RX_BYTES, - NL80211_STA_INFO_TX_BYTES, - NL80211_STA_INFO_LLID, - NL80211_STA_INFO_PLID, - NL80211_STA_INFO_PLINK_STATE, - NL80211_STA_INFO_SIGNAL, - NL80211_STA_INFO_TX_BITRATE, - NL80211_STA_INFO_RX_PACKETS, - NL80211_STA_INFO_TX_PACKETS, - - /* keep last */ - __NL80211_STA_INFO_AFTER_LAST, - NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1 -}; - -/** - * enum nl80211_mpath_flags - nl80211 mesh path flags - * - * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active - * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running - * @NL80211_MPATH_FLAG_SN_VALID: the mesh path contains a valid SN - * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set - * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded - */ -enum nl80211_mpath_flags { - NL80211_MPATH_FLAG_ACTIVE = 1<<0, - NL80211_MPATH_FLAG_RESOLVING = 1<<1, - NL80211_MPATH_FLAG_SN_VALID = 1<<2, - NL80211_MPATH_FLAG_FIXED = 1<<3, - NL80211_MPATH_FLAG_RESOLVED = 1<<4, -}; - -/** - * enum nl80211_mpath_info - mesh path information - * - * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting - * information about a mesh path. - * - * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved - * @NL80211_ATTR_MPATH_FRAME_QLEN: number of queued frames for this destination - * @NL80211_ATTR_MPATH_SN: destination sequence number - * @NL80211_ATTR_MPATH_METRIC: metric (cost) of this mesh path - * @NL80211_ATTR_MPATH_EXPTIME: expiration time for the path, in msec from now - * @NL80211_ATTR_MPATH_FLAGS: mesh path flags, enumerated in - * &enum nl80211_mpath_flags; - * @NL80211_ATTR_MPATH_DISCOVERY_TIMEOUT: total path discovery timeout, in msec - * @NL80211_ATTR_MPATH_DISCOVERY_RETRIES: mesh path discovery retries - */ -enum nl80211_mpath_info { - __NL80211_MPATH_INFO_INVALID, - NL80211_MPATH_INFO_FRAME_QLEN, - NL80211_MPATH_INFO_SN, - NL80211_MPATH_INFO_METRIC, - NL80211_MPATH_INFO_EXPTIME, - NL80211_MPATH_INFO_FLAGS, - NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, - NL80211_MPATH_INFO_DISCOVERY_RETRIES, - - /* keep last */ - __NL80211_MPATH_INFO_AFTER_LAST, - NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1 -}; - -/** - * enum nl80211_band_attr - band attributes - * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved - * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band, - * an array of nested frequency attributes - * @NL80211_BAND_ATTR_RATES: supported bitrates in this band, - * an array of nested bitrate attributes - * @NL80211_BAND_ATTR_HT_MCS_SET: 16-byte attribute containing the MCS set as - * defined in 802.11n - * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE - * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n - * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n - */ -enum nl80211_band_attr { - __NL80211_BAND_ATTR_INVALID, - NL80211_BAND_ATTR_FREQS, - NL80211_BAND_ATTR_RATES, - - NL80211_BAND_ATTR_HT_MCS_SET, - NL80211_BAND_ATTR_HT_CAPA, - NL80211_BAND_ATTR_HT_AMPDU_FACTOR, - NL80211_BAND_ATTR_HT_AMPDU_DENSITY, - - /* keep last */ - __NL80211_BAND_ATTR_AFTER_LAST, - NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 -}; - -#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA - -/** - * enum nl80211_frequency_attr - frequency attributes - * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz - * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current - * regulatory domain. - * @NL80211_FREQUENCY_ATTR_PASSIVE_SCAN: Only passive scanning is - * permitted on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_NO_IBSS: IBSS networks are not permitted - * on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory - * on this channel in current regulatory domain. - * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm - * (100 * dBm). - */ -enum nl80211_frequency_attr { - __NL80211_FREQUENCY_ATTR_INVALID, - NL80211_FREQUENCY_ATTR_FREQ, - NL80211_FREQUENCY_ATTR_DISABLED, - NL80211_FREQUENCY_ATTR_PASSIVE_SCAN, - NL80211_FREQUENCY_ATTR_NO_IBSS, - NL80211_FREQUENCY_ATTR_RADAR, - NL80211_FREQUENCY_ATTR_MAX_TX_POWER, - - /* keep last */ - __NL80211_FREQUENCY_ATTR_AFTER_LAST, - NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1 -}; - -#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER - -/** - * enum nl80211_bitrate_attr - bitrate attributes - * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps - * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported - * in 2.4 GHz band. - */ -enum nl80211_bitrate_attr { - __NL80211_BITRATE_ATTR_INVALID, - NL80211_BITRATE_ATTR_RATE, - NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE, - - /* keep last */ - __NL80211_BITRATE_ATTR_AFTER_LAST, - NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1 -}; - -/** - * enum nl80211_initiator - Indicates the initiator of a reg domain request - * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world - * regulatory domain. - * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the - * regulatory domain. - * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the - * wireless core it thinks its knows the regulatory domain we should be in. - * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an - * 802.11 country information element with regulatory information it - * thinks we should consider. - */ -enum nl80211_reg_initiator { - NL80211_REGDOM_SET_BY_CORE, - NL80211_REGDOM_SET_BY_USER, - NL80211_REGDOM_SET_BY_DRIVER, - NL80211_REGDOM_SET_BY_COUNTRY_IE, -}; - -/** - * enum nl80211_reg_type - specifies the type of regulatory domain - * @NL80211_REGDOM_TYPE_COUNTRY: the regulatory domain set is one that pertains - * to a specific country. When this is set you can count on the - * ISO / IEC 3166 alpha2 country code being valid. - * @NL80211_REGDOM_TYPE_WORLD: the regulatory set domain is the world regulatory - * domain. - * @NL80211_REGDOM_TYPE_CUSTOM_WORLD: the regulatory domain set is a custom - * driver specific world regulatory domain. These do not apply system-wide - * and are only applicable to the individual devices which have requested - * them to be applied. - * @NL80211_REGDOM_TYPE_INTERSECTION: the regulatory domain set is the product - * of an intersection between two regulatory domains -- the previously - * set regulatory domain on the system and the last accepted regulatory - * domain request to be processed. - */ -enum nl80211_reg_type { - NL80211_REGDOM_TYPE_COUNTRY, - NL80211_REGDOM_TYPE_WORLD, - NL80211_REGDOM_TYPE_CUSTOM_WORLD, - NL80211_REGDOM_TYPE_INTERSECTION, -}; - -/** - * enum nl80211_reg_rule_attr - regulatory rule attributes - * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional - * considerations for a given frequency range. These are the - * &enum nl80211_reg_rule_flags. - * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory - * rule in KHz. This is not a center of frequency but an actual regulatory - * band edge. - * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule - * in KHz. This is not a center a frequency but an actual regulatory - * band edge. - * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this - * frequency range, in KHz. - * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain - * for a given frequency range. The value is in mBi (100 * dBi). - * If you don't have one then don't send this. - * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for - * a given frequency range. The value is in mBm (100 * dBm). - */ -enum nl80211_reg_rule_attr { - __NL80211_REG_RULE_ATTR_INVALID, - NL80211_ATTR_REG_RULE_FLAGS, - - NL80211_ATTR_FREQ_RANGE_START, - NL80211_ATTR_FREQ_RANGE_END, - NL80211_ATTR_FREQ_RANGE_MAX_BW, - - NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, - NL80211_ATTR_POWER_RULE_MAX_EIRP, - - /* keep last */ - __NL80211_REG_RULE_ATTR_AFTER_LAST, - NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 -}; - -/** - * enum nl80211_reg_rule_flags - regulatory rule flags - * - * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed - * @NL80211_RRF_NO_CCK: CCK modulation not allowed - * @NL80211_RRF_NO_INDOOR: indoor operation not allowed - * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed - * @NL80211_RRF_DFS: DFS support is required to be used - * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links - * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links - * @NL80211_RRF_PASSIVE_SCAN: passive scan is required - * @NL80211_RRF_NO_IBSS: no IBSS is allowed - */ -enum nl80211_reg_rule_flags { - NL80211_RRF_NO_OFDM = 1<<0, - NL80211_RRF_NO_CCK = 1<<1, - NL80211_RRF_NO_INDOOR = 1<<2, - NL80211_RRF_NO_OUTDOOR = 1<<3, - NL80211_RRF_DFS = 1<<4, - NL80211_RRF_PTP_ONLY = 1<<5, - NL80211_RRF_PTMP_ONLY = 1<<6, - NL80211_RRF_PASSIVE_SCAN = 1<<7, - NL80211_RRF_NO_IBSS = 1<<8, -}; - -/** - * enum nl80211_survey_info - survey information - * - * These attribute types are used with %NL80211_ATTR_SURVEY_INFO - * when getting information about a survey. - * - * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved - * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel - * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) - */ -enum nl80211_survey_info { - __NL80211_SURVEY_INFO_INVALID, - NL80211_SURVEY_INFO_FREQUENCY, - NL80211_SURVEY_INFO_NOISE, - - /* keep last */ - __NL80211_SURVEY_INFO_AFTER_LAST, - NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1 -}; - -/** - * enum nl80211_mntr_flags - monitor configuration flags - * - * Monitor configuration flags. - * - * @__NL80211_MNTR_FLAG_INVALID: reserved - * - * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS - * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP - * @NL80211_MNTR_FLAG_CONTROL: pass control frames - * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering - * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing. - * overrides all other flags. - * - * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use - * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag - */ -enum nl80211_mntr_flags { - __NL80211_MNTR_FLAG_INVALID, - NL80211_MNTR_FLAG_FCSFAIL, - NL80211_MNTR_FLAG_PLCPFAIL, - NL80211_MNTR_FLAG_CONTROL, - NL80211_MNTR_FLAG_OTHER_BSS, - NL80211_MNTR_FLAG_COOK_FRAMES, - - /* keep last */ - __NL80211_MNTR_FLAG_AFTER_LAST, - NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1 -}; - -/** - * enum nl80211_meshconf_params - mesh configuration parameters - * - * Mesh configuration parameters - * - * @__NL80211_MESHCONF_INVALID: internal use - * - * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in - * millisecond units, used by the Peer Link Open message - * - * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the inital confirm timeout, in - * millisecond units, used by the peer link management to close a peer link - * - * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in - * millisecond units - * - * @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed - * on this mesh interface - * - * @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link - * open retries that can be sent to establish a new peer link instance in a - * mesh - * - * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh - * point. - * - * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically - * open peer links when we detect compatible mesh peers. - * - * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames - * containing a PREQ that an MP can send to a particular destination (path - * target) - * - * @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths - * (in milliseconds) - * - * @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait - * until giving up on a path discovery (in milliseconds) - * - * @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh - * points receiving a PREQ shall consider the forwarding information from the - * root to be valid. (TU = time unit) - * - * @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in - * TUs) during which an MP can send only one action frame containing a PREQ - * reference element - * - * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs) - * that it takes for an HWMP information element to propagate across the mesh - * - * @NL80211_MESHCONF_ROOTMODE: whether root mode is enabled or not - * - * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute - * - * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use - */ -enum nl80211_meshconf_params { - __NL80211_MESHCONF_INVALID, - NL80211_MESHCONF_RETRY_TIMEOUT, - NL80211_MESHCONF_CONFIRM_TIMEOUT, - NL80211_MESHCONF_HOLDING_TIMEOUT, - NL80211_MESHCONF_MAX_PEER_LINKS, - NL80211_MESHCONF_MAX_RETRIES, - NL80211_MESHCONF_TTL, - NL80211_MESHCONF_AUTO_OPEN_PLINKS, - NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, - NL80211_MESHCONF_PATH_REFRESH_TIME, - NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, - NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, - NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, - NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, - NL80211_MESHCONF_HWMP_ROOTMODE, - - /* keep last */ - __NL80211_MESHCONF_ATTR_AFTER_LAST, - NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1 -}; - -/** - * enum nl80211_txq_attr - TX queue parameter attributes - * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved - * @NL80211_TXQ_ATTR_QUEUE: TX queue identifier (NL80211_TXQ_Q_*) - * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning - * disabled - * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form - * 2^n-1 in the range 1..32767] - * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form - * 2^n-1 in the range 1..32767] - * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255] - * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal - * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number - */ -enum nl80211_txq_attr { - __NL80211_TXQ_ATTR_INVALID, - NL80211_TXQ_ATTR_QUEUE, - NL80211_TXQ_ATTR_TXOP, - NL80211_TXQ_ATTR_CWMIN, - NL80211_TXQ_ATTR_CWMAX, - NL80211_TXQ_ATTR_AIFS, - - /* keep last */ - __NL80211_TXQ_ATTR_AFTER_LAST, - NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1 -}; - -enum nl80211_txq_q { - NL80211_TXQ_Q_VO, - NL80211_TXQ_Q_VI, - NL80211_TXQ_Q_BE, - NL80211_TXQ_Q_BK -}; - -enum nl80211_channel_type { - NL80211_CHAN_NO_HT, - NL80211_CHAN_HT20, - NL80211_CHAN_HT40MINUS, - NL80211_CHAN_HT40PLUS -}; - -/** - * enum nl80211_bss - netlink attributes for a BSS - * - * @__NL80211_BSS_INVALID: invalid - * @NL80211_BSS_FREQUENCY: frequency in MHz (u32) - * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64) - * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16) - * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16) - * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the - * raw information elements from the probe response/beacon (bin) - * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon - * in mBm (100 * dBm) (s32) - * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon - * in unspecified units, scaled to 0..100 (u8) - * @NL80211_BSS_STATUS: status, if this BSS is "used" - * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms - * @__NL80211_BSS_AFTER_LAST: internal - * @NL80211_BSS_MAX: highest BSS attribute - */ -enum nl80211_bss { - __NL80211_BSS_INVALID, - NL80211_BSS_BSSID, - NL80211_BSS_FREQUENCY, - NL80211_BSS_TSF, - NL80211_BSS_BEACON_INTERVAL, - NL80211_BSS_CAPABILITY, - NL80211_BSS_INFORMATION_ELEMENTS, - NL80211_BSS_SIGNAL_MBM, - NL80211_BSS_SIGNAL_UNSPEC, - NL80211_BSS_STATUS, - NL80211_BSS_SEEN_MS_AGO, - - /* keep last */ - __NL80211_BSS_AFTER_LAST, - NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1 -}; - -/** - * enum nl80211_bss_status - BSS "status" - */ -enum nl80211_bss_status { - NL80211_BSS_STATUS_AUTHENTICATED, - NL80211_BSS_STATUS_ASSOCIATED, - NL80211_BSS_STATUS_IBSS_JOINED, -}; - -/** - * enum nl80211_auth_type - AuthenticationType - * - * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication - * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only) - * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r) - * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP) - * @__NL80211_AUTHTYPE_NUM: internal - * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm - * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by - * trying multiple times); this is invalid in netlink -- leave out - * the attribute for this on CONNECT commands. - */ -enum nl80211_auth_type { - NL80211_AUTHTYPE_OPEN_SYSTEM, - NL80211_AUTHTYPE_SHARED_KEY, - NL80211_AUTHTYPE_FT, - NL80211_AUTHTYPE_NETWORK_EAP, - - /* keep last */ - __NL80211_AUTHTYPE_NUM, - NL80211_AUTHTYPE_MAX = __NL80211_AUTHTYPE_NUM - 1, - NL80211_AUTHTYPE_AUTOMATIC -}; - -/** - * enum nl80211_key_type - Key Type - * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key - * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key - * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS) - */ -enum nl80211_key_type { - NL80211_KEYTYPE_GROUP, - NL80211_KEYTYPE_PAIRWISE, - NL80211_KEYTYPE_PEERKEY, -}; - -/** - * enum nl80211_mfp - Management frame protection state - * @NL80211_MFP_NO: Management frame protection not used - * @NL80211_MFP_REQUIRED: Management frame protection required - */ -enum nl80211_mfp { - NL80211_MFP_NO, - NL80211_MFP_REQUIRED, -}; - -enum nl80211_wpa_versions { - NL80211_WPA_VERSION_1 = 1 << 0, - NL80211_WPA_VERSION_2 = 1 << 1, -}; - -/** - * enum nl80211_key_attributes - key attributes - * @__NL80211_KEY_INVALID: invalid - * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of - * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC - * keys - * @NL80211_KEY_IDX: key ID (u8, 0-3) - * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 - * section 7.3.2.25.1, e.g. 0x000FAC04) - * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and - * CCMP keys, each six bytes in little endian - * @NL80211_KEY_DEFAULT: flag indicating default key - * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key - * @__NL80211_KEY_AFTER_LAST: internal - * @NL80211_KEY_MAX: highest key attribute - */ -enum nl80211_key_attributes { - __NL80211_KEY_INVALID, - NL80211_KEY_DATA, - NL80211_KEY_IDX, - NL80211_KEY_CIPHER, - NL80211_KEY_SEQ, - NL80211_KEY_DEFAULT, - NL80211_KEY_DEFAULT_MGMT, - - /* keep last */ - __NL80211_KEY_AFTER_LAST, - NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1 -}; - -#endif /* __LINUX_NL80211_H */ diff --git a/contrib/wpa/src/common/privsep_commands.h b/contrib/wpa/src/common/privsep_commands.h index 81b7f5432ecc..cc900be9d20e 100644 --- a/contrib/wpa/src/common/privsep_commands.h +++ b/contrib/wpa/src/common/privsep_commands.h @@ -18,7 +18,6 @@ enum privsep_cmd { PRIVSEP_CMD_REGISTER, PRIVSEP_CMD_UNREGISTER, - PRIVSEP_CMD_SET_WPA, PRIVSEP_CMD_SCAN, PRIVSEP_CMD_GET_SCAN_RESULTS, PRIVSEP_CMD_ASSOCIATE, @@ -30,7 +29,6 @@ enum privsep_cmd { PRIVSEP_CMD_L2_UNREGISTER, PRIVSEP_CMD_L2_NOTIFY_AUTH_START, PRIVSEP_CMD_L2_SEND, - PRIVSEP_CMD_SET_MODE, PRIVSEP_CMD_SET_COUNTRY, }; @@ -72,7 +70,6 @@ enum privsep_event { PRIVSEP_EVENT_STKSTART, PRIVSEP_EVENT_FT_RESPONSE, PRIVSEP_EVENT_RX_EAPOL, - PRIVSEP_EVENT_STA_RX, }; #endif /* PRIVSEP_COMMANDS_H */ diff --git a/contrib/wpa/src/common/version.h b/contrib/wpa/src/common/version.h index b79c4949c4da..02f34be3ab12 100644 --- a/contrib/wpa/src/common/version.h +++ b/contrib/wpa/src/common/version.h @@ -1,6 +1,6 @@ #ifndef VERSION_H #define VERSION_H -#define VERSION_STR "0.6.10" +#define VERSION_STR "0.7.3" #endif /* VERSION_H */ diff --git a/contrib/wpa/src/common/wireless_copy.h b/contrib/wpa/src/common/wireless_copy.h deleted file mode 100644 index ad764663766f..000000000000 --- a/contrib/wpa/src/common/wireless_copy.h +++ /dev/null @@ -1,1099 +0,0 @@ -/* This is based on Linux Wireless Extensions header file from WIRELESS_EXT 18. - * I have just removed kernel related headers and added some typedefs etc. to - * make this easier to include into user space programs. - * Jouni Malinen, 2005-03-12. - */ - - -/* - * This file define a set of standard wireless extensions - * - * Version : 19 18.3.05 - * - * Authors : Jean Tourrilhes - HPL - - * Copyright (c) 1997-2005 Jean Tourrilhes, All Rights Reserved. - */ - -#ifndef _LINUX_WIRELESS_H -#define _LINUX_WIRELESS_H - -/************************** DOCUMENTATION **************************/ -/* - * Initial APIs (1996 -> onward) : - * ----------------------------- - * Basically, the wireless extensions are for now a set of standard ioctl - * call + /proc/net/wireless - * - * The entry /proc/net/wireless give statistics and information on the - * driver. - * This is better than having each driver having its entry because - * its centralised and we may remove the driver module safely. - * - * Ioctl are used to configure the driver and issue commands. This is - * better than command line options of insmod because we may want to - * change dynamically (while the driver is running) some parameters. - * - * The ioctl mechanimsm are copied from standard devices ioctl. - * We have the list of command plus a structure descibing the - * data exchanged... - * Note that to add these ioctl, I was obliged to modify : - * # net/core/dev.c (two place + add include) - * # net/ipv4/af_inet.c (one place + add include) - * - * /proc/net/wireless is a copy of /proc/net/dev. - * We have a structure for data passed from the driver to /proc/net/wireless - * Too add this, I've modified : - * # net/core/dev.c (two other places) - * # include/linux/netdevice.h (one place) - * # include/linux/proc_fs.h (one place) - * - * New driver API (2002 -> onward) : - * ------------------------------- - * This file is only concerned with the user space API and common definitions. - * The new driver API is defined and documented in : - * # include/net/iw_handler.h - * - * Note as well that /proc/net/wireless implementation has now moved in : - * # net/core/wireless.c - * - * Wireless Events (2002 -> onward) : - * -------------------------------- - * Events are defined at the end of this file, and implemented in : - * # net/core/wireless.c - * - * Other comments : - * -------------- - * Do not add here things that are redundant with other mechanisms - * (drivers init, ifconfig, /proc/net/dev, ...) and with are not - * wireless specific. - * - * These wireless extensions are not magic : each driver has to provide - * support for them... - * - * IMPORTANT NOTE : As everything in the kernel, this is very much a - * work in progress. Contact me if you have ideas of improvements... - */ - -/***************************** INCLUDES *****************************/ - - /* jkm - replaced linux headers with C library headers, added typedefs */ -#if 0 -/* To minimise problems in user space, I might remove those headers - * at some point. Jean II */ -#include /* for "caddr_t" et al */ -#include /* for "struct sockaddr" et al */ -#include /* for IFNAMSIZ and co... */ -#else -#include -#include -typedef __uint32_t __u32; -typedef __int32_t __s32; -typedef __uint16_t __u16; -typedef __int16_t __s16; -typedef __uint8_t __u8; -#ifndef __user -#define __user -#endif /* __user */ -#endif - -/***************************** VERSION *****************************/ -/* - * This constant is used to know the availability of the wireless - * extensions and to know which version of wireless extensions it is - * (there is some stuff that will be added in the future...) - * I just plan to increment with each new version. - */ -#define WIRELESS_EXT 19 - -/* - * Changes : - * - * V2 to V3 - * -------- - * Alan Cox start some incompatibles changes. I've integrated a bit more. - * - Encryption renamed to Encode to avoid US regulation problems - * - Frequency changed from float to struct to avoid problems on old 386 - * - * V3 to V4 - * -------- - * - Add sensitivity - * - * V4 to V5 - * -------- - * - Missing encoding definitions in range - * - Access points stuff - * - * V5 to V6 - * -------- - * - 802.11 support (ESSID ioctls) - * - * V6 to V7 - * -------- - * - define IW_ESSID_MAX_SIZE and IW_MAX_AP - * - * V7 to V8 - * -------- - * - Changed my e-mail address - * - More 802.11 support (nickname, rate, rts, frag) - * - List index in frequencies - * - * V8 to V9 - * -------- - * - Support for 'mode of operation' (ad-hoc, managed...) - * - Support for unicast and multicast power saving - * - Change encoding to support larger tokens (>64 bits) - * - Updated iw_params (disable, flags) and use it for NWID - * - Extracted iw_point from iwreq for clarity - * - * V9 to V10 - * --------- - * - Add PM capability to range structure - * - Add PM modifier : MAX/MIN/RELATIVE - * - Add encoding option : IW_ENCODE_NOKEY - * - Add TxPower ioctls (work like TxRate) - * - * V10 to V11 - * ---------- - * - Add WE version in range (help backward/forward compatibility) - * - Add retry ioctls (work like PM) - * - * V11 to V12 - * ---------- - * - Add SIOCSIWSTATS to get /proc/net/wireless programatically - * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space - * - Add new statistics (frag, retry, beacon) - * - Add average quality (for user space calibration) - * - * V12 to V13 - * ---------- - * - Document creation of new driver API. - * - Extract union iwreq_data from struct iwreq (for new driver API). - * - Rename SIOCSIWNAME as SIOCSIWCOMMIT - * - * V13 to V14 - * ---------- - * - Wireless Events support : define struct iw_event - * - Define additional specific event numbers - * - Add "addr" and "param" fields in union iwreq_data - * - AP scanning stuff (SIOCSIWSCAN and friends) - * - * V14 to V15 - * ---------- - * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg - * - Make struct iw_freq signed (both m & e), add explicit padding - * - Add IWEVCUSTOM for driver specific event/scanning token - * - Add IW_MAX_GET_SPY for driver returning a lot of addresses - * - Add IW_TXPOW_RANGE for range of Tx Powers - * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points - * - Add IW_MODE_MONITOR for passive monitor - * - * V15 to V16 - * ---------- - * - Increase the number of bitrates in iw_range to 32 (for 802.11g) - * - Increase the number of frequencies in iw_range to 32 (for 802.11b+a) - * - Reshuffle struct iw_range for increases, add filler - * - Increase IW_MAX_AP to 64 for driver returning a lot of addresses - * - Remove IW_MAX_GET_SPY because conflict with enhanced spy support - * - Add SIOCSIWTHRSPY/SIOCGIWTHRSPY and "struct iw_thrspy" - * - Add IW_ENCODE_TEMP and iw_range->encoding_login_index - * - * V16 to V17 - * ---------- - * - Add flags to frequency -> auto/fixed - * - Document (struct iw_quality *)->updated, add new flags (INVALID) - * - Wireless Event capability in struct iw_range - * - Add support for relative TxPower (yick !) - * - * V17 to V18 (From Jouni Malinen ) - * ---------- - * - Add support for WPA/WPA2 - * - Add extended encoding configuration (SIOCSIWENCODEEXT and - * SIOCGIWENCODEEXT) - * - Add SIOCSIWGENIE/SIOCGIWGENIE - * - Add SIOCSIWMLME - * - Add SIOCSIWPMKSA - * - Add struct iw_range bit field for supported encoding capabilities - * - Add optional scan request parameters for SIOCSIWSCAN - * - Add SIOCSIWAUTH/SIOCGIWAUTH for setting authentication and WPA - * related parameters (extensible up to 4096 parameter values) - * - Add wireless events: IWEVGENIE, IWEVMICHAELMICFAILURE, - * IWEVASSOCREQIE, IWEVASSOCRESPIE, IWEVPMKIDCAND - * - * V18 to V19 - * ---------- - * - Remove (struct iw_point *)->pointer from events and streams - * - Remove header includes to help user space - * - Increase IW_ENCODING_TOKEN_MAX from 32 to 64 - * - Add IW_QUAL_ALL_UPDATED and IW_QUAL_ALL_INVALID macros - * - Add explicit flag to tell stats are in dBm : IW_QUAL_DBM - * - Add IW_IOCTL_IDX() and IW_EVENT_IDX() macros - */ - -/**************************** CONSTANTS ****************************/ - -/* -------------------------- IOCTL LIST -------------------------- */ - -/* Wireless Identification */ -#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ -#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ -/* SIOCGIWNAME is used to verify the presence of Wireless Extensions. - * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... - * Don't put the name of your driver there, it's useless. */ - -/* Basic operations */ -#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ -#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ -#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ -#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ -#define SIOCSIWMODE 0x8B06 /* set operation mode */ -#define SIOCGIWMODE 0x8B07 /* get operation mode */ -#define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ -#define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ - -/* Informative stuff */ -#define SIOCSIWRANGE 0x8B0A /* Unused */ -#define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ -#define SIOCSIWPRIV 0x8B0C /* Unused */ -#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ -#define SIOCSIWSTATS 0x8B0E /* Unused */ -#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ -/* SIOCGIWSTATS is strictly used between user space and the kernel, and - * is never passed to the driver (i.e. the driver will never see it). */ - -/* Spy support (statistics per MAC address - used for Mobile IP support) */ -#define SIOCSIWSPY 0x8B10 /* set spy addresses */ -#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ -#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ -#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ - -/* Access Point manipulation */ -#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ -#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ -#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ -#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ -#define SIOCGIWSCAN 0x8B19 /* get scanning results */ - -/* 802.11 specific support */ -#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ -#define SIOCGIWESSID 0x8B1B /* get ESSID */ -#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ -#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ -/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit - * within the 'iwreq' structure, so we need to use the 'data' member to - * point to a string in user space, like it is done for RANGE... */ - -/* Other parameters useful in 802.11 and some other devices */ -#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ -#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ -#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ -#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ -#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ -#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ -#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ -#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ -#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ -#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ - -/* Encoding stuff (scrambling, hardware security, WEP...) */ -#define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ -#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ -/* Power saving stuff (power management, unicast and multicast) */ -#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ -#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ - -/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). - * This ioctl uses struct iw_point and data buffer that includes IE id and len - * fields. More than one IE may be included in the request. Setting the generic - * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers - * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers - * are required to report the used IE as a wireless event, e.g., when - * associating with an AP. */ -#define SIOCSIWGENIE 0x8B30 /* set generic IE */ -#define SIOCGIWGENIE 0x8B31 /* get generic IE */ - -/* WPA : IEEE 802.11 MLME requests */ -#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses - * struct iw_mlme */ -/* WPA : Authentication mode parameters */ -#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ -#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ - -/* WPA : Extended version of encoding configuration */ -#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ -#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ - -/* WPA2 : PMKSA cache management */ -#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ - -/* -------------------- DEV PRIVATE IOCTL LIST -------------------- */ - -/* These 32 ioctl are wireless device private, for 16 commands. - * Each driver is free to use them for whatever purpose it chooses, - * however the driver *must* export the description of those ioctls - * with SIOCGIWPRIV and *must* use arguments as defined below. - * If you don't follow those rules, DaveM is going to hate you (reason : - * it make mixed 32/64bit operation impossible). - */ -#define SIOCIWFIRSTPRIV 0x8BE0 -#define SIOCIWLASTPRIV 0x8BFF -/* Previously, we were using SIOCDEVPRIVATE, but we now have our - * separate range because of collisions with other tools such as - * 'mii-tool'. - * We now have 32 commands, so a bit more space ;-). - * Also, all 'odd' commands are only usable by root and don't return the - * content of ifr/iwr to user (but you are not obliged to use the set/get - * convention, just use every other two command). More details in iwpriv.c. - * And I repeat : you are not forced to use them with iwpriv, but you - * must be compliant with it. - */ - -/* ------------------------- IOCTL STUFF ------------------------- */ - -/* The first and the last (range) */ -#define SIOCIWFIRST 0x8B00 -#define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ -#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) - -/* Even : get (world access), odd : set (root access) */ -#define IW_IS_SET(cmd) (!((cmd) & 0x1)) -#define IW_IS_GET(cmd) ((cmd) & 0x1) - -/* ----------------------- WIRELESS EVENTS ----------------------- */ -/* Those are *NOT* ioctls, do not issue request on them !!! */ -/* Most events use the same identifier as ioctl requests */ - -#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ -#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ -#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ -#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ -#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ -#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) - * (scan results); This includes id and - * length fields. One IWEVGENIE may - * contain more than one IE. Scan - * results may contain one or more - * IWEVGENIE events. */ -#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure - * (struct iw_michaelmicfailure) - */ -#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. - * The data includes id and length - * fields and may contain more than one - * IE. This event is required in - * Managed mode if the driver - * generates its own WPA/RSN IE. This - * should be sent just before - * IWEVREGISTERED event for the - * association. */ -#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association - * Response. The data includes id and - * length fields and may contain more - * than one IE. This may be sent - * between IWEVASSOCREQIE and - * IWEVREGISTERED events for the - * association. */ -#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN - * pre-authentication - * (struct iw_pmkid_cand) */ - -#define IWEVFIRST 0x8C00 -#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) - -/* ------------------------- PRIVATE INFO ------------------------- */ -/* - * The following is used with SIOCGIWPRIV. It allow a driver to define - * the interface (name, type of data) for its private ioctl. - * Privates ioctl are SIOCIWFIRSTPRIV -> SIOCIWLASTPRIV - */ - -#define IW_PRIV_TYPE_MASK 0x7000 /* Type of arguments */ -#define IW_PRIV_TYPE_NONE 0x0000 -#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */ -#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */ -#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */ -#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */ -#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */ - -#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed number of args */ - -#define IW_PRIV_SIZE_MASK 0x07FF /* Max number of those args */ - -/* - * Note : if the number of args is fixed and the size < 16 octets, - * instead of passing a pointer we will put args in the iwreq struct... - */ - -/* ----------------------- OTHER CONSTANTS ----------------------- */ - -/* Maximum frequencies in the range struct */ -#define IW_MAX_FREQUENCIES 32 -/* Note : if you have something like 80 frequencies, - * don't increase this constant and don't fill the frequency list. - * The user will be able to set by channel anyway... */ - -/* Maximum bit rates in the range struct */ -#define IW_MAX_BITRATES 32 - -/* Maximum tx powers in the range struct */ -#define IW_MAX_TXPOWER 8 -/* Note : if you more than 8 TXPowers, just set the max and min or - * a few of them in the struct iw_range. */ - -/* Maximum of address that you may set with SPY */ -#define IW_MAX_SPY 8 - -/* Maximum of address that you may get in the - list of access points in range */ -#define IW_MAX_AP 64 - -/* Maximum size of the ESSID and NICKN strings */ -#define IW_ESSID_MAX_SIZE 32 - -/* Modes of operation */ -#define IW_MODE_AUTO 0 /* Let the driver decides */ -#define IW_MODE_ADHOC 1 /* Single cell network */ -#define IW_MODE_INFRA 2 /* Multi cell network, roaming, ... */ -#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */ -#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */ -#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */ -#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */ - -/* Statistics flags (bitmask in updated) */ -#define IW_QUAL_QUAL_UPDATED 0x01 /* Value was updated since last read */ -#define IW_QUAL_LEVEL_UPDATED 0x02 -#define IW_QUAL_NOISE_UPDATED 0x04 -#define IW_QUAL_ALL_UPDATED 0x07 -#define IW_QUAL_DBM 0x08 /* Level + Noise are dBm */ -#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ -#define IW_QUAL_LEVEL_INVALID 0x20 -#define IW_QUAL_NOISE_INVALID 0x40 -#define IW_QUAL_ALL_INVALID 0x70 - -/* Frequency flags */ -#define IW_FREQ_AUTO 0x00 /* Let the driver decides */ -#define IW_FREQ_FIXED 0x01 /* Force a specific value */ - -/* Maximum number of size of encoding token available - * they are listed in the range structure */ -#define IW_MAX_ENCODING_SIZES 8 - -/* Maximum size of the encoding token in bytes */ -#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */ - -/* Flags for encoding (along with the token) */ -#define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ -#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ -#define IW_ENCODE_MODE 0xF000 /* Modes defined below */ -#define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ -#define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ -#define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ -#define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ -#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ -#define IW_ENCODE_TEMP 0x0400 /* Temporary key */ - -/* Power management flags available (along with the value, if any) */ -#define IW_POWER_ON 0x0000 /* No details... */ -#define IW_POWER_TYPE 0xF000 /* Type of parameter */ -#define IW_POWER_PERIOD 0x1000 /* Value is a period/duration of */ -#define IW_POWER_TIMEOUT 0x2000 /* Value is a timeout (to go asleep) */ -#define IW_POWER_MODE 0x0F00 /* Power Management mode */ -#define IW_POWER_UNICAST_R 0x0100 /* Receive only unicast messages */ -#define IW_POWER_MULTICAST_R 0x0200 /* Receive only multicast messages */ -#define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ -#define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ -#define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ -#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ -#define IW_POWER_MIN 0x0001 /* Value is a minimum */ -#define IW_POWER_MAX 0x0002 /* Value is a maximum */ -#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ - -/* Transmit Power flags available */ -#define IW_TXPOW_TYPE 0x00FF /* Type of value */ -#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ -#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ -#define IW_TXPOW_RELATIVE 0x0002 /* Value is in arbitrary units */ -#define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */ - -/* Retry limits and lifetime flags available */ -#define IW_RETRY_ON 0x0000 /* No details... */ -#define IW_RETRY_TYPE 0xF000 /* Type of parameter */ -#define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ -#define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ -#define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ -#define IW_RETRY_MIN 0x0001 /* Value is a minimum */ -#define IW_RETRY_MAX 0x0002 /* Value is a maximum */ -#define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ - -/* Scanning request flags */ -#define IW_SCAN_DEFAULT 0x0000 /* Default scan of the driver */ -#define IW_SCAN_ALL_ESSID 0x0001 /* Scan all ESSIDs */ -#define IW_SCAN_THIS_ESSID 0x0002 /* Scan only this ESSID */ -#define IW_SCAN_ALL_FREQ 0x0004 /* Scan all Frequencies */ -#define IW_SCAN_THIS_FREQ 0x0008 /* Scan only this Frequency */ -#define IW_SCAN_ALL_MODE 0x0010 /* Scan all Modes */ -#define IW_SCAN_THIS_MODE 0x0020 /* Scan only this Mode */ -#define IW_SCAN_ALL_RATE 0x0040 /* Scan all Bit-Rates */ -#define IW_SCAN_THIS_RATE 0x0080 /* Scan only this Bit-Rate */ -/* struct iw_scan_req scan_type */ -#define IW_SCAN_TYPE_ACTIVE 0 -#define IW_SCAN_TYPE_PASSIVE 1 -/* Maximum size of returned data */ -#define IW_SCAN_MAX_DATA 4096 /* In bytes */ - -/* Max number of char in custom event - use multiple of them if needed */ -#define IW_CUSTOM_MAX 256 /* In bytes */ - -/* Generic information element */ -#define IW_GENERIC_IE_MAX 1024 - -/* MLME requests (SIOCSIWMLME / struct iw_mlme) */ -#define IW_MLME_DEAUTH 0 -#define IW_MLME_DISASSOC 1 - -/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ -#define IW_AUTH_INDEX 0x0FFF -#define IW_AUTH_FLAGS 0xF000 -/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) - * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the - * parameter that is being set/get to; value will be read/written to - * struct iw_param value field) */ -#define IW_AUTH_WPA_VERSION 0 -#define IW_AUTH_CIPHER_PAIRWISE 1 -#define IW_AUTH_CIPHER_GROUP 2 -#define IW_AUTH_KEY_MGMT 3 -#define IW_AUTH_TKIP_COUNTERMEASURES 4 -#define IW_AUTH_DROP_UNENCRYPTED 5 -#define IW_AUTH_80211_AUTH_ALG 6 -#define IW_AUTH_WPA_ENABLED 7 -#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 -#define IW_AUTH_ROAMING_CONTROL 9 -#define IW_AUTH_PRIVACY_INVOKED 10 -#define IW_AUTH_CIPHER_GROUP_MGMT 11 -#define IW_AUTH_MFP 12 - -/* IW_AUTH_WPA_VERSION values (bit field) */ -#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 -#define IW_AUTH_WPA_VERSION_WPA 0x00000002 -#define IW_AUTH_WPA_VERSION_WPA2 0x00000004 - -/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ -#define IW_AUTH_CIPHER_NONE 0x00000001 -#define IW_AUTH_CIPHER_WEP40 0x00000002 -#define IW_AUTH_CIPHER_TKIP 0x00000004 -#define IW_AUTH_CIPHER_CCMP 0x00000008 -#define IW_AUTH_CIPHER_WEP104 0x00000010 - -/* IW_AUTH_KEY_MGMT values (bit field) */ -#define IW_AUTH_KEY_MGMT_802_1X 1 -#define IW_AUTH_KEY_MGMT_PSK 2 - -/* IW_AUTH_80211_AUTH_ALG values (bit field) */ -#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 -#define IW_AUTH_ALG_SHARED_KEY 0x00000002 -#define IW_AUTH_ALG_LEAP 0x00000004 - -/* IW_AUTH_ROAMING_CONTROL values */ -#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ -#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming - * control */ - -/* IW_AUTH_MFP (management frame protection) values */ -#define IW_AUTH_MFP_DISABLED 0 /* MFP disabled */ -#define IW_AUTH_MFP_OPTIONAL 1 /* MFP optional */ -#define IW_AUTH_MFP_REQUIRED 2 /* MFP required */ - -/* SIOCSIWENCODEEXT definitions */ -#define IW_ENCODE_SEQ_MAX_SIZE 8 -/* struct iw_encode_ext ->alg */ -#define IW_ENCODE_ALG_NONE 0 -#define IW_ENCODE_ALG_WEP 1 -#define IW_ENCODE_ALG_TKIP 2 -#define IW_ENCODE_ALG_CCMP 3 -#define IW_ENCODE_ALG_PMK 4 -#define IW_ENCODE_ALG_AES_CMAC 5 -/* struct iw_encode_ext ->ext_flags */ -#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 -#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 -#define IW_ENCODE_EXT_GROUP_KEY 0x00000004 -#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 - -/* IWEVMICHAELMICFAILURE : struct iw_michaelmicfailure ->flags */ -#define IW_MICFAILURE_KEY_ID 0x00000003 /* Key ID 0..3 */ -#define IW_MICFAILURE_GROUP 0x00000004 -#define IW_MICFAILURE_PAIRWISE 0x00000008 -#define IW_MICFAILURE_STAKEY 0x00000010 -#define IW_MICFAILURE_COUNT 0x00000060 /* 1 or 2 (0 = count not supported) - */ - -/* Bit field values for enc_capa in struct iw_range */ -#define IW_ENC_CAPA_WPA 0x00000001 -#define IW_ENC_CAPA_WPA2 0x00000002 -#define IW_ENC_CAPA_CIPHER_TKIP 0x00000004 -#define IW_ENC_CAPA_CIPHER_CCMP 0x00000008 -#define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010 - -/* Event capability macros - in (struct iw_range *)->event_capa - * Because we have more than 32 possible events, we use an array of - * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ -#define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ - (cmd - SIOCIWFIRSTPRIV + 0x60) : \ - (cmd - SIOCSIWCOMMIT)) -#define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) -#define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) -/* Event capability constants - event autogenerated by the kernel - * This list is valid for most 802.11 devices, customise as needed... */ -#define IW_EVENT_CAPA_K_0 (IW_EVENT_CAPA_MASK(0x8B04) | \ - IW_EVENT_CAPA_MASK(0x8B06) | \ - IW_EVENT_CAPA_MASK(0x8B1A)) -#define IW_EVENT_CAPA_K_1 (IW_EVENT_CAPA_MASK(0x8B2A)) -/* "Easy" macro to set events in iw_range (less efficient) */ -#define IW_EVENT_CAPA_SET(event_capa, cmd) (event_capa[IW_EVENT_CAPA_INDEX(cmd)] |= IW_EVENT_CAPA_MASK(cmd)) -#define IW_EVENT_CAPA_SET_KERNEL(event_capa) {event_capa[0] |= IW_EVENT_CAPA_K_0; event_capa[1] |= IW_EVENT_CAPA_K_1; } - - -/****************************** TYPES ******************************/ - -/* --------------------------- SUBTYPES --------------------------- */ -/* - * Generic format for most parameters that fit in an int - */ -struct iw_param -{ - __s32 value; /* The value of the parameter itself */ - __u8 fixed; /* Hardware should not use auto select */ - __u8 disabled; /* Disable the feature */ - __u16 flags; /* Various specifc flags (if any) */ -}; - -/* - * For all data larger than 16 octets, we need to use a - * pointer to memory allocated in user space. - */ -struct iw_point -{ - void __user *pointer; /* Pointer to the data (in user space) */ - __u16 length; /* number of fields or size in bytes */ - __u16 flags; /* Optional params */ -}; - -/* - * A frequency - * For numbers lower than 10^9, we encode the number in 'm' and - * set 'e' to 0 - * For number greater than 10^9, we divide it by the lowest power - * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... - * The power of 10 is in 'e', the result of the division is in 'm'. - */ -struct iw_freq -{ - __s32 m; /* Mantissa */ - __s16 e; /* Exponent */ - __u8 i; /* List index (when in range struct) */ - __u8 flags; /* Flags (fixed/auto) */ -}; - -/* - * Quality of the link - */ -struct iw_quality -{ - __u8 qual; /* link quality (%retries, SNR, - %missed beacons or better...) */ - __u8 level; /* signal level (dBm) */ - __u8 noise; /* noise level (dBm) */ - __u8 updated; /* Flags to know if updated */ -}; - -/* - * Packet discarded in the wireless adapter due to - * "wireless" specific problems... - * Note : the list of counter and statistics in net_device_stats - * is already pretty exhaustive, and you should use that first. - * This is only additional stats... - */ -struct iw_discarded -{ - __u32 nwid; /* Rx : Wrong nwid/essid */ - __u32 code; /* Rx : Unable to code/decode (WEP) */ - __u32 fragment; /* Rx : Can't perform MAC reassembly */ - __u32 retries; /* Tx : Max MAC retries num reached */ - __u32 misc; /* Others cases */ -}; - -/* - * Packet/Time period missed in the wireless adapter due to - * "wireless" specific problems... - */ -struct iw_missed -{ - __u32 beacon; /* Missed beacons/superframe */ -}; - -/* - * Quality range (for spy threshold) - */ -struct iw_thrspy -{ - struct sockaddr addr; /* Source address (hw/mac) */ - struct iw_quality qual; /* Quality of the link */ - struct iw_quality low; /* Low threshold */ - struct iw_quality high; /* High threshold */ -}; - -/* - * Optional data for scan request - * - * Note: these optional parameters are controlling parameters for the - * scanning behavior, these do not apply to getting scan results - * (SIOCGIWSCAN). Drivers are expected to keep a local BSS table and - * provide a merged results with all BSSes even if the previous scan - * request limited scanning to a subset, e.g., by specifying an SSID. - * Especially, scan results are required to include an entry for the - * current BSS if the driver is in Managed mode and associated with an AP. - */ -struct iw_scan_req -{ - __u8 scan_type; /* IW_SCAN_TYPE_{ACTIVE,PASSIVE} */ - __u8 essid_len; - __u8 num_channels; /* num entries in channel_list; - * 0 = scan all allowed channels */ - __u8 flags; /* reserved as padding; use zero, this may - * be used in the future for adding flags - * to request different scan behavior */ - struct sockaddr bssid; /* ff:ff:ff:ff:ff:ff for broadcast BSSID or - * individual address of a specific BSS */ - - /* - * Use this ESSID if IW_SCAN_THIS_ESSID flag is used instead of using - * the current ESSID. This allows scan requests for specific ESSID - * without having to change the current ESSID and potentially breaking - * the current association. - */ - __u8 essid[IW_ESSID_MAX_SIZE]; - - /* - * Optional parameters for changing the default scanning behavior. - * These are based on the MLME-SCAN.request from IEEE Std 802.11. - * TU is 1.024 ms. If these are set to 0, driver is expected to use - * reasonable default values. min_channel_time defines the time that - * will be used to wait for the first reply on each channel. If no - * replies are received, next channel will be scanned after this. If - * replies are received, total time waited on the channel is defined by - * max_channel_time. - */ - __u32 min_channel_time; /* in TU */ - __u32 max_channel_time; /* in TU */ - - struct iw_freq channel_list[IW_MAX_FREQUENCIES]; -}; - -/* ------------------------- WPA SUPPORT ------------------------- */ - -/* - * Extended data structure for get/set encoding (this is used with - * SIOCSIWENCODEEXT/SIOCGIWENCODEEXT. struct iw_point and IW_ENCODE_* - * flags are used in the same way as with SIOCSIWENCODE/SIOCGIWENCODE and - * only the data contents changes (key data -> this structure, including - * key data). - * - * If the new key is the first group key, it will be set as the default - * TX key. Otherwise, default TX key index is only changed if - * IW_ENCODE_EXT_SET_TX_KEY flag is set. - * - * Key will be changed with SIOCSIWENCODEEXT in all cases except for - * special "change TX key index" operation which is indicated by setting - * key_len = 0 and ext_flags |= IW_ENCODE_EXT_SET_TX_KEY. - * - * tx_seq/rx_seq are only used when respective - * IW_ENCODE_EXT_{TX,RX}_SEQ_VALID flag is set in ext_flags. Normal - * TKIP/CCMP operation is to set RX seq with SIOCSIWENCODEEXT and start - * TX seq from zero whenever key is changed. SIOCGIWENCODEEXT is normally - * used only by an Authenticator (AP or an IBSS station) to get the - * current TX sequence number. Using TX_SEQ_VALID for SIOCSIWENCODEEXT and - * RX_SEQ_VALID for SIOCGIWENCODEEXT are optional, but can be useful for - * debugging/testing. - */ -struct iw_encode_ext -{ - __u32 ext_flags; /* IW_ENCODE_EXT_* */ - __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ - __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ - struct sockaddr addr; /* ff:ff:ff:ff:ff:ff for broadcast/multicast - * (group) keys or unicast address for - * individual keys */ - __u16 alg; /* IW_ENCODE_ALG_* */ - __u16 key_len; - __u8 key[0]; -}; - -/* SIOCSIWMLME data */ -struct iw_mlme -{ - __u16 cmd; /* IW_MLME_* */ - __u16 reason_code; - struct sockaddr addr; -}; - -/* SIOCSIWPMKSA data */ -#define IW_PMKSA_ADD 1 -#define IW_PMKSA_REMOVE 2 -#define IW_PMKSA_FLUSH 3 - -#define IW_PMKID_LEN 16 - -struct iw_pmksa -{ - __u32 cmd; /* IW_PMKSA_* */ - struct sockaddr bssid; - __u8 pmkid[IW_PMKID_LEN]; -}; - -/* IWEVMICHAELMICFAILURE data */ -struct iw_michaelmicfailure -{ - __u32 flags; - struct sockaddr src_addr; - __u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; /* LSB first */ -}; - -/* IWEVPMKIDCAND data */ -#define IW_PMKID_CAND_PREAUTH 0x00000001 /* RNS pre-authentication enabled */ -struct iw_pmkid_cand -{ - __u32 flags; /* IW_PMKID_CAND_* */ - __u32 index; /* the smaller the index, the higher the - * priority */ - struct sockaddr bssid; -}; - -/* ------------------------ WIRELESS STATS ------------------------ */ -/* - * Wireless statistics (used for /proc/net/wireless) - */ -struct iw_statistics -{ - __u16 status; /* Status - * - device dependent for now */ - - struct iw_quality qual; /* Quality of the link - * (instant/mean/max) */ - struct iw_discarded discard; /* Packet discarded counts */ - struct iw_missed miss; /* Packet missed counts */ -}; - -/* ------------------------ IOCTL REQUEST ------------------------ */ -/* - * This structure defines the payload of an ioctl, and is used - * below. - * - * Note that this structure should fit on the memory footprint - * of iwreq (which is the same as ifreq), which mean a max size of - * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... - * You should check this when increasing the structures defined - * above in this file... - */ -union iwreq_data -{ - /* Config - generic */ - char name[IFNAMSIZ]; - /* Name : used to verify the presence of wireless extensions. - * Name of the protocol/provider... */ - - struct iw_point essid; /* Extended network name */ - struct iw_param nwid; /* network id (or domain - the cell) */ - struct iw_freq freq; /* frequency or channel : - * 0-1000 = channel - * > 1000 = frequency in Hz */ - - struct iw_param sens; /* signal level threshold */ - struct iw_param bitrate; /* default bit rate */ - struct iw_param txpower; /* default transmit power */ - struct iw_param rts; /* RTS threshold threshold */ - struct iw_param frag; /* Fragmentation threshold */ - __u32 mode; /* Operation mode */ - struct iw_param retry; /* Retry limits & lifetime */ - - struct iw_point encoding; /* Encoding stuff : tokens */ - struct iw_param power; /* PM duration/timeout */ - struct iw_quality qual; /* Quality part of statistics */ - - struct sockaddr ap_addr; /* Access point address */ - struct sockaddr addr; /* Destination address (hw/mac) */ - - struct iw_param param; /* Other small parameters */ - struct iw_point data; /* Other large parameters */ -}; - -/* - * The structure to exchange data for ioctl. - * This structure is the same as 'struct ifreq', but (re)defined for - * convenience... - * Do I need to remind you about structure size (32 octets) ? - */ -struct iwreq -{ - union - { - char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ - } ifr_ifrn; - - /* Data part (defined just above) */ - union iwreq_data u; -}; - -/* -------------------------- IOCTL DATA -------------------------- */ -/* - * For those ioctl which want to exchange mode data that what could - * fit in the above structure... - */ - -/* - * Range of parameters - */ - -struct iw_range -{ - /* Informative stuff (to choose between different interface) */ - __u32 throughput; /* To give an idea... */ - /* In theory this value should be the maximum benchmarked - * TCP/IP throughput, because with most of these devices the - * bit rate is meaningless (overhead an co) to estimate how - * fast the connection will go and pick the fastest one. - * I suggest people to play with Netperf or any benchmark... - */ - - /* NWID (or domain id) */ - __u32 min_nwid; /* Minimal NWID we are able to set */ - __u32 max_nwid; /* Maximal NWID we are able to set */ - - /* Old Frequency (backward compat - moved lower ) */ - __u16 old_num_channels; - __u8 old_num_frequency; - - /* Wireless event capability bitmasks */ - __u32 event_capa[6]; - - /* signal level threshold range */ - __s32 sensitivity; - - /* Quality of link & SNR stuff */ - /* Quality range (link, level, noise) - * If the quality is absolute, it will be in the range [0 ; max_qual], - * if the quality is dBm, it will be in the range [max_qual ; 0]. - * Don't forget that we use 8 bit arithmetics... */ - struct iw_quality max_qual; /* Quality of the link */ - /* This should contain the average/typical values of the quality - * indicator. This should be the threshold between a "good" and - * a "bad" link (example : monitor going from green to orange). - * Currently, user space apps like quality monitors don't have any - * way to calibrate the measurement. With this, they can split - * the range between 0 and max_qual in different quality level - * (using a geometric subdivision centered on the average). - * I expect that people doing the user space apps will feedback - * us on which value we need to put in each driver... */ - struct iw_quality avg_qual; /* Quality of the link */ - - /* Rates */ - __u8 num_bitrates; /* Number of entries in the list */ - __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ - - /* RTS threshold */ - __s32 min_rts; /* Minimal RTS threshold */ - __s32 max_rts; /* Maximal RTS threshold */ - - /* Frag threshold */ - __s32 min_frag; /* Minimal frag threshold */ - __s32 max_frag; /* Maximal frag threshold */ - - /* Power Management duration & timeout */ - __s32 min_pmp; /* Minimal PM period */ - __s32 max_pmp; /* Maximal PM period */ - __s32 min_pmt; /* Minimal PM timeout */ - __s32 max_pmt; /* Maximal PM timeout */ - __u16 pmp_flags; /* How to decode max/min PM period */ - __u16 pmt_flags; /* How to decode max/min PM timeout */ - __u16 pm_capa; /* What PM options are supported */ - - /* Encoder stuff */ - __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ - __u8 num_encoding_sizes; /* Number of entry in the list */ - __u8 max_encoding_tokens; /* Max number of tokens */ - /* For drivers that need a "login/passwd" form */ - __u8 encoding_login_index; /* token index for login token */ - - /* Transmit power */ - __u16 txpower_capa; /* What options are supported */ - __u8 num_txpower; /* Number of entries in the list */ - __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ - - /* Wireless Extension version info */ - __u8 we_version_compiled; /* Must be WIRELESS_EXT */ - __u8 we_version_source; /* Last update of source */ - - /* Retry limits and lifetime */ - __u16 retry_capa; /* What retry options are supported */ - __u16 retry_flags; /* How to decode max/min retry limit */ - __u16 r_time_flags; /* How to decode max/min retry life */ - __s32 min_retry; /* Minimal number of retries */ - __s32 max_retry; /* Maximal number of retries */ - __s32 min_r_time; /* Minimal retry lifetime */ - __s32 max_r_time; /* Maximal retry lifetime */ - - /* Frequency */ - __u16 num_channels; /* Number of channels [0; num - 1] */ - __u8 num_frequency; /* Number of entry in the list */ - struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ - /* Note : this frequency list doesn't need to fit channel numbers, - * because each entry contain its channel index */ - - __u32 enc_capa; /* IW_ENC_CAPA_* bit field */ -}; - -/* - * Private ioctl interface information - */ - -struct iw_priv_args -{ - __u32 cmd; /* Number of the ioctl to issue */ - __u16 set_args; /* Type and number of args */ - __u16 get_args; /* Type and number of args */ - char name[IFNAMSIZ]; /* Name of the extension */ -}; - -/* ----------------------- WIRELESS EVENTS ----------------------- */ -/* - * Wireless events are carried through the rtnetlink socket to user - * space. They are encapsulated in the IFLA_WIRELESS field of - * a RTM_NEWLINK message. - */ - -/* - * A Wireless Event. Contains basically the same data as the ioctl... - */ -struct iw_event -{ - __u16 len; /* Real lenght of this stuff */ - __u16 cmd; /* Wireless IOCTL */ - union iwreq_data u; /* IOCTL fixed payload */ -}; - -/* Size of the Event prefix (including padding and alignement junk) */ -#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) -/* Size of the various events */ -#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) -#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) -#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) -#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) -#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) -#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) - -/* iw_point events are special. First, the payload (extra data) come at - * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second, - * we omit the pointer, so start at an offset. */ -#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ - (char *) NULL) -#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ - IW_EV_POINT_OFF) - -#endif /* _LINUX_WIRELESS_H */ diff --git a/contrib/wpa/src/common/wpa_common.c b/contrib/wpa/src/common/wpa_common.c index 074cb8064060..b295f315624a 100644 --- a/contrib/wpa/src/common/wpa_common.c +++ b/contrib/wpa/src/common/wpa_common.c @@ -15,11 +15,11 @@ #include "includes.h" #include "common.h" -#include "md5.h" -#include "sha1.h" -#include "sha256.h" -#include "aes_wrap.h" -#include "crypto.h" +#include "crypto/md5.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "crypto/aes_wrap.h" +#include "crypto/crypto.h" #include "ieee802_11_defs.h" #include "defs.h" #include "wpa_common.h" @@ -50,10 +50,10 @@ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, switch (ver) { case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: - hmac_md5(key, 16, buf, len, mic); - break; + return hmac_md5(key, 16, buf, len, mic); case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: - hmac_sha1(key, 16, buf, len, hash); + if (hmac_sha1(key, 16, buf, len, hash)) + return -1; os_memcpy(mic, hash, MD5_MAC_LEN); break; #if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) @@ -568,3 +568,220 @@ void wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, } #endif /* CONFIG_IEEE80211R */ + + +/** + * rsn_pmkid - Calculate PMK identifier + * @pmk: Pairwise master key + * @pmk_len: Length of pmk in bytes + * @aa: Authenticator address + * @spa: Supplicant address + * @pmkid: Buffer for PMKID + * @use_sha256: Whether to use SHA256-based KDF + * + * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy + * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) + */ +void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, + u8 *pmkid, int use_sha256) +{ + char *title = "PMK Name"; + const u8 *addr[3]; + const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; + unsigned char hash[SHA256_MAC_LEN]; + + addr[0] = (u8 *) title; + addr[1] = aa; + addr[2] = spa; + +#ifdef CONFIG_IEEE80211W + if (use_sha256) + hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); + else +#endif /* CONFIG_IEEE80211W */ + hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); + os_memcpy(pmkid, hash, PMKID_LEN); +} + + +/** + * wpa_cipher_txt - Convert cipher suite to a text string + * @cipher: Cipher suite (WPA_CIPHER_* enum) + * Returns: Pointer to a text string of the cipher suite name + */ +const char * wpa_cipher_txt(int cipher) +{ + switch (cipher) { + case WPA_CIPHER_NONE: + return "NONE"; + case WPA_CIPHER_WEP40: + return "WEP-40"; + case WPA_CIPHER_WEP104: + return "WEP-104"; + case WPA_CIPHER_TKIP: + return "TKIP"; + case WPA_CIPHER_CCMP: + return "CCMP"; + case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP: + return "CCMP+TKIP"; + default: + return "UNKNOWN"; + } +} + + +/** + * wpa_key_mgmt_txt - Convert key management suite to a text string + * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum) + * @proto: WPA/WPA2 version (WPA_PROTO_*) + * Returns: Pointer to a text string of the key management suite name + */ +const char * wpa_key_mgmt_txt(int key_mgmt, int proto) +{ + switch (key_mgmt) { + case WPA_KEY_MGMT_IEEE8021X: + if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) + return "WPA2+WPA/IEEE 802.1X/EAP"; + return proto == WPA_PROTO_RSN ? + "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP"; + case WPA_KEY_MGMT_PSK: + if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) + return "WPA2-PSK+WPA-PSK"; + return proto == WPA_PROTO_RSN ? + "WPA2-PSK" : "WPA-PSK"; + case WPA_KEY_MGMT_NONE: + return "NONE"; + case WPA_KEY_MGMT_IEEE8021X_NO_WPA: + return "IEEE 802.1X (no WPA)"; +#ifdef CONFIG_IEEE80211R + case WPA_KEY_MGMT_FT_IEEE8021X: + return "FT-EAP"; + case WPA_KEY_MGMT_FT_PSK: + return "FT-PSK"; +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + case WPA_KEY_MGMT_IEEE8021X_SHA256: + return "WPA2-EAP-SHA256"; + case WPA_KEY_MGMT_PSK_SHA256: + return "WPA2-PSK-SHA256"; +#endif /* CONFIG_IEEE80211W */ + default: + return "UNKNOWN"; + } +} + + +int wpa_compare_rsn_ie(int ft_initial_assoc, + const u8 *ie1, size_t ie1len, + const u8 *ie2, size_t ie2len) +{ + if (ie1 == NULL || ie2 == NULL) + return -1; + + if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0) + return 0; /* identical IEs */ + +#ifdef CONFIG_IEEE80211R + if (ft_initial_assoc) { + struct wpa_ie_data ie1d, ie2d; + /* + * The PMKID-List in RSN IE is different between Beacon/Probe + * Response/(Re)Association Request frames and EAPOL-Key + * messages in FT initial mobility domain association. Allow + * for this, but verify that other parts of the RSN IEs are + * identical. + */ + if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 || + wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0) + return -1; + if (ie1d.proto == ie2d.proto && + ie1d.pairwise_cipher == ie2d.pairwise_cipher && + ie1d.group_cipher == ie2d.group_cipher && + ie1d.key_mgmt == ie2d.key_mgmt && + ie1d.capabilities == ie2d.capabilities && + ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher) + return 0; + } +#endif /* CONFIG_IEEE80211R */ + + return -1; +} + + +#ifdef CONFIG_IEEE80211R +int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid) +{ + u8 *start, *end, *rpos, *rend; + int added = 0; + + start = ies; + end = ies + ies_len; + + while (start < end) { + if (*start == WLAN_EID_RSN) + break; + start += 2 + start[1]; + } + if (start >= end) { + wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in " + "IEs data"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification", + start, 2 + start[1]); + + /* Find start of PMKID-Count */ + rpos = start + 2; + rend = rpos + start[1]; + + /* Skip Version and Group Data Cipher Suite */ + rpos += 2 + 4; + /* Skip Pairwise Cipher Suite Count and List */ + rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; + /* Skip AKM Suite Count and List */ + rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; + + if (rpos == rend) { + /* Add RSN Capabilities */ + os_memmove(rpos + 2, rpos, end - rpos); + *rpos++ = 0; + *rpos++ = 0; + } else { + /* Skip RSN Capabilities */ + rpos += 2; + if (rpos > rend) { + wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in " + "IEs data"); + return -1; + } + } + + if (rpos == rend) { + /* No PMKID-Count field included; add it */ + os_memmove(rpos + 2 + PMKID_LEN, rpos, end - rpos); + WPA_PUT_LE16(rpos, 1); + rpos += 2; + os_memcpy(rpos, pmkid, PMKID_LEN); + added += 2 + PMKID_LEN; + start[1] += 2 + PMKID_LEN; + } else { + /* PMKID-Count was included; use it */ + if (WPA_GET_LE16(rpos) != 0) { + wpa_printf(MSG_ERROR, "FT: Unexpected PMKID " + "in RSN IE in EAPOL-Key data"); + return -1; + } + WPA_PUT_LE16(rpos, 1); + rpos += 2; + os_memmove(rpos + PMKID_LEN, rpos, end - rpos); + os_memcpy(rpos, pmkid, PMKID_LEN); + added += PMKID_LEN; + start[1] += PMKID_LEN; + } + + wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification " + "(PMKID inserted)", start, 2 + start[1]); + + return added; +} +#endif /* CONFIG_IEEE80211R */ diff --git a/contrib/wpa/src/common/wpa_common.h b/contrib/wpa/src/common/wpa_common.h index 3074cd44a136..fd8a79fd602e 100644 --- a/contrib/wpa/src/common/wpa_common.h +++ b/contrib/wpa/src/common/wpa_common.h @@ -282,6 +282,12 @@ struct rsn_ftie { #define FTIE_SUBELEM_R0KH_ID 3 #define FTIE_SUBELEM_IGTK 4 +struct rsn_rdie { + u8 id; + u8 descr_count; + le16 status_code; +} STRUCT_PACKED; + #endif /* CONFIG_IEEE80211R */ #ifdef _MSC_VER @@ -332,4 +338,14 @@ struct wpa_ie_data { int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data); +void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, + u8 *pmkid, int use_sha256); + +const char * wpa_cipher_txt(int cipher); +const char * wpa_key_mgmt_txt(int key_mgmt, int proto); +int wpa_compare_rsn_ie(int ft_initial_assoc, + const u8 *ie1, size_t ie1len, + const u8 *ie2, size_t ie2len); +int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid); + #endif /* WPA_COMMON_H */ diff --git a/contrib/wpa/src/common/wpa_ctrl.h b/contrib/wpa/src/common/wpa_ctrl.h index 1bfc0d645346..d770fd42d94f 100644 --- a/contrib/wpa/src/common/wpa_ctrl.h +++ b/contrib/wpa/src/common/wpa_ctrl.h @@ -40,14 +40,24 @@ extern "C" { #define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION " /** EAP authentication started (EAP-Request/Identity received) */ #define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED " +/** EAP method proposed by the server */ +#define WPA_EVENT_EAP_PROPOSED_METHOD "CTRL-EVENT-EAP-PROPOSED-METHOD " /** EAP method selected */ #define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD " +/** EAP peer certificate from TLS */ +#define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT " +/** EAP TLS certificate chain validation error */ +#define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR " /** EAP authentication completed successfully */ #define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS " /** EAP authentication failed (EAP-Failure received) */ #define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE " /** New scan results available */ #define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS " +/** A new BSS entry was added (followed by BSS entry id and BSSID) */ +#define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED " +/** A BSS entry was removed (followed by BSS entry id and BSSID) */ +#define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED " /** WPS overlap detected in PBC mode */ #define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED " @@ -69,11 +79,24 @@ extern "C" { /** WPS enrollment attempt timed out and was terminated */ #define WPS_EVENT_TIMEOUT "WPS-TIMEOUT " +#define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN " + +/* WPS ER events */ +#define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD " +#define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE " +#define WPS_EVENT_ER_ENROLLEE_ADD "WPS-ER-ENROLLEE-ADD " +#define WPS_EVENT_ER_ENROLLEE_REMOVE "WPS-ER-ENROLLEE-REMOVE " + /* hostapd control interface - fixed message prefixes */ #define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED " #define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS " #define WPS_EVENT_REG_SUCCESS "WPS-REG-SUCCESS " #define WPS_EVENT_AP_SETUP_LOCKED "WPS-AP-SETUP-LOCKED " +#define WPS_EVENT_AP_SETUP_UNLOCKED "WPS-AP-SETUP-UNLOCKED " +#define WPS_EVENT_AP_PIN_ENABLED "WPS-AP-PIN-ENABLED " +#define WPS_EVENT_AP_PIN_DISABLED "WPS-AP-PIN-DISABLED " +#define AP_STA_CONNECTED "AP-STA-CONNECTED " +#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED " /* wpa_supplicant/hostapd control interface access */ diff --git a/contrib/wpa/src/crypto/.gitignore b/contrib/wpa/src/crypto/.gitignore new file mode 100644 index 000000000000..ee606048c417 --- /dev/null +++ b/contrib/wpa/src/crypto/.gitignore @@ -0,0 +1 @@ +libcrypto.a diff --git a/contrib/wpa/src/crypto/Makefile b/contrib/wpa/src/crypto/Makefile index cffba620da04..69aa16ac66b0 100644 --- a/contrib/wpa/src/crypto/Makefile +++ b/contrib/wpa/src/crypto/Makefile @@ -1,9 +1,56 @@ -all: - @echo Nothing to be made. +all: libcrypto.a clean: - for d in $(SUBDIRS); do make -C $$d clean; done - rm -f *~ *.o *.d + rm -f *~ *.o *.d libcrypto.a install: @echo Nothing to be made. + + +include ../lib.rules + +CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT +CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER +#CFLAGS += -DALL_DH_GROUPS + +LIB_OBJS= \ + aes-cbc.o \ + aes-ctr.o \ + aes-eax.o \ + aes-encblock.o \ + aes-internal.o \ + aes-internal-dec.o \ + aes-internal-enc.o \ + aes-omac1.o \ + aes-unwrap.o \ + aes-wrap.o \ + des-internal.o \ + dh_group5.o \ + dh_groups.o \ + md4-internal.o \ + md5.o \ + md5-internal.o \ + md5-non-fips.o \ + milenage.o \ + ms_funcs.o \ + rc4.o \ + sha1.o \ + sha1-internal.o \ + sha1-pbkdf2.o \ + sha1-tlsprf.o \ + sha1-tprf.o \ + sha256.o \ + sha256-internal.o + +LIB_OBJS += crypto_internal.o +LIB_OBJS += crypto_internal-cipher.o +LIB_OBJS += crypto_internal-modexp.o +LIB_OBJS += crypto_internal-rsa.o +LIB_OBJS += tls_internal.o +LIB_OBJS += fips_prf_internal.o + + +libcrypto.a: $(LIB_OBJS) + $(AR) crT $@ $? + +-include $(OBJS:%.o=%.d) diff --git a/contrib/wpa/src/crypto/aes-cbc.c b/contrib/wpa/src/crypto/aes-cbc.c new file mode 100644 index 000000000000..bd74769905e1 --- /dev/null +++ b/contrib/wpa/src/crypto/aes-cbc.c @@ -0,0 +1,86 @@ +/* + * AES-128 CBC + * + * Copyright (c) 2003-2007, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "aes.h" +#include "aes_wrap.h" + +/** + * aes_128_cbc_encrypt - AES-128 CBC encryption + * @key: Encryption key + * @iv: Encryption IV for CBC mode (16 bytes) + * @data: Data to encrypt in-place + * @data_len: Length of data in bytes (must be divisible by 16) + * Returns: 0 on success, -1 on failure + */ +int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) +{ + void *ctx; + u8 cbc[AES_BLOCK_SIZE]; + u8 *pos = data; + int i, j, blocks; + + ctx = aes_encrypt_init(key, 16); + if (ctx == NULL) + return -1; + os_memcpy(cbc, iv, AES_BLOCK_SIZE); + + blocks = data_len / AES_BLOCK_SIZE; + for (i = 0; i < blocks; i++) { + for (j = 0; j < AES_BLOCK_SIZE; j++) + cbc[j] ^= pos[j]; + aes_encrypt(ctx, cbc, cbc); + os_memcpy(pos, cbc, AES_BLOCK_SIZE); + pos += AES_BLOCK_SIZE; + } + aes_encrypt_deinit(ctx); + return 0; +} + + +/** + * aes_128_cbc_decrypt - AES-128 CBC decryption + * @key: Decryption key + * @iv: Decryption IV for CBC mode (16 bytes) + * @data: Data to decrypt in-place + * @data_len: Length of data in bytes (must be divisible by 16) + * Returns: 0 on success, -1 on failure + */ +int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) +{ + void *ctx; + u8 cbc[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE]; + u8 *pos = data; + int i, j, blocks; + + ctx = aes_decrypt_init(key, 16); + if (ctx == NULL) + return -1; + os_memcpy(cbc, iv, AES_BLOCK_SIZE); + + blocks = data_len / AES_BLOCK_SIZE; + for (i = 0; i < blocks; i++) { + os_memcpy(tmp, pos, AES_BLOCK_SIZE); + aes_decrypt(ctx, pos, pos); + for (j = 0; j < AES_BLOCK_SIZE; j++) + pos[j] ^= cbc[j]; + os_memcpy(cbc, tmp, AES_BLOCK_SIZE); + pos += AES_BLOCK_SIZE; + } + aes_decrypt_deinit(ctx); + return 0; +} diff --git a/contrib/wpa/src/crypto/aes-ctr.c b/contrib/wpa/src/crypto/aes-ctr.c new file mode 100644 index 000000000000..468f87741199 --- /dev/null +++ b/contrib/wpa/src/crypto/aes-ctr.c @@ -0,0 +1,61 @@ +/* + * AES-128 CTR + * + * Copyright (c) 2003-2007, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "aes.h" +#include "aes_wrap.h" + +/** + * aes_128_ctr_encrypt - AES-128 CTR mode encryption + * @key: Key for encryption (16 bytes) + * @nonce: Nonce for counter mode (16 bytes) + * @data: Data to encrypt in-place + * @data_len: Length of data in bytes + * Returns: 0 on success, -1 on failure + */ +int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, + u8 *data, size_t data_len) +{ + void *ctx; + size_t j, len, left = data_len; + int i; + u8 *pos = data; + u8 counter[AES_BLOCK_SIZE], buf[AES_BLOCK_SIZE]; + + ctx = aes_encrypt_init(key, 16); + if (ctx == NULL) + return -1; + os_memcpy(counter, nonce, AES_BLOCK_SIZE); + + while (left > 0) { + aes_encrypt(ctx, counter, buf); + + len = (left < AES_BLOCK_SIZE) ? left : AES_BLOCK_SIZE; + for (j = 0; j < len; j++) + pos[j] ^= buf[j]; + pos += len; + left -= len; + + for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { + counter[i]++; + if (counter[i]) + break; + } + } + aes_encrypt_deinit(ctx); + return 0; +} diff --git a/contrib/wpa/src/crypto/aes-eax.c b/contrib/wpa/src/crypto/aes-eax.c new file mode 100644 index 000000000000..d5c397151d2e --- /dev/null +++ b/contrib/wpa/src/crypto/aes-eax.c @@ -0,0 +1,151 @@ +/* + * AES-128 EAX + * + * Copyright (c) 2003-2007, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "aes.h" +#include "aes_wrap.h" + +/** + * aes_128_eax_encrypt - AES-128 EAX mode encryption + * @key: Key for encryption (16 bytes) + * @nonce: Nonce for counter mode + * @nonce_len: Nonce length in bytes + * @hdr: Header data to be authenticity protected + * @hdr_len: Length of the header data bytes + * @data: Data to encrypt in-place + * @data_len: Length of data in bytes + * @tag: 16-byte tag value + * Returns: 0 on success, -1 on failure + */ +int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len, + const u8 *hdr, size_t hdr_len, + u8 *data, size_t data_len, u8 *tag) +{ + u8 *buf; + size_t buf_len; + u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE], + data_mac[AES_BLOCK_SIZE]; + int i, ret = -1; + + if (nonce_len > data_len) + buf_len = nonce_len; + else + buf_len = data_len; + if (hdr_len > buf_len) + buf_len = hdr_len; + buf_len += 16; + + buf = os_malloc(buf_len); + if (buf == NULL) + return -1; + + os_memset(buf, 0, 15); + + buf[15] = 0; + os_memcpy(buf + 16, nonce, nonce_len); + if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) + goto fail; + + buf[15] = 1; + os_memcpy(buf + 16, hdr, hdr_len); + if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) + goto fail; + + if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len)) + goto fail; + buf[15] = 2; + os_memcpy(buf + 16, data, data_len); + if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) + goto fail; + + for (i = 0; i < AES_BLOCK_SIZE; i++) + tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]; + + ret = 0; +fail: + os_free(buf); + + return ret; +} + + +/** + * aes_128_eax_decrypt - AES-128 EAX mode decryption + * @key: Key for decryption (16 bytes) + * @nonce: Nonce for counter mode + * @nonce_len: Nonce length in bytes + * @hdr: Header data to be authenticity protected + * @hdr_len: Length of the header data bytes + * @data: Data to encrypt in-place + * @data_len: Length of data in bytes + * @tag: 16-byte tag value + * Returns: 0 on success, -1 on failure, -2 if tag does not match + */ +int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len, + const u8 *hdr, size_t hdr_len, + u8 *data, size_t data_len, const u8 *tag) +{ + u8 *buf; + size_t buf_len; + u8 nonce_mac[AES_BLOCK_SIZE], hdr_mac[AES_BLOCK_SIZE], + data_mac[AES_BLOCK_SIZE]; + int i; + + if (nonce_len > data_len) + buf_len = nonce_len; + else + buf_len = data_len; + if (hdr_len > buf_len) + buf_len = hdr_len; + buf_len += 16; + + buf = os_malloc(buf_len); + if (buf == NULL) + return -1; + + os_memset(buf, 0, 15); + + buf[15] = 0; + os_memcpy(buf + 16, nonce, nonce_len); + if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) { + os_free(buf); + return -1; + } + + buf[15] = 1; + os_memcpy(buf + 16, hdr, hdr_len); + if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) { + os_free(buf); + return -1; + } + + buf[15] = 2; + os_memcpy(buf + 16, data, data_len); + if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) { + os_free(buf); + return -1; + } + + os_free(buf); + + for (i = 0; i < AES_BLOCK_SIZE; i++) { + if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i])) + return -2; + } + + return aes_128_ctr_encrypt(key, nonce_mac, data, data_len); +} diff --git a/contrib/wpa/src/crypto/aes-encblock.c b/contrib/wpa/src/crypto/aes-encblock.c new file mode 100644 index 000000000000..8f35caa221e2 --- /dev/null +++ b/contrib/wpa/src/crypto/aes-encblock.c @@ -0,0 +1,38 @@ +/* + * AES encrypt_block + * + * Copyright (c) 2003-2007, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "aes.h" +#include "aes_wrap.h" + +/** + * aes_128_encrypt_block - Perform one AES 128-bit block operation + * @key: Key for AES + * @in: Input data (16 bytes) + * @out: Output of the AES block operation (16 bytes) + * Returns: 0 on success, -1 on failure + */ +int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out) +{ + void *ctx; + ctx = aes_encrypt_init(key, 16); + if (ctx == NULL) + return -1; + aes_encrypt(ctx, in, out); + aes_encrypt_deinit(ctx); + return 0; +} diff --git a/contrib/wpa/src/crypto/aes-internal-dec.c b/contrib/wpa/src/crypto/aes-internal-dec.c new file mode 100644 index 000000000000..2d32c03fbf4c --- /dev/null +++ b/contrib/wpa/src/crypto/aes-internal-dec.c @@ -0,0 +1,151 @@ +/* + * AES (Rijndael) cipher - decrypt + * + * Modifications to public domain implementation: + * - support only 128-bit keys + * - cleanup + * - use C pre-processor to make it easier to change S table access + * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at + * cost of reduced throughput (quite small difference on Pentium 4, + * 10-25% when using -O1 or -O2 optimization) + * + * Copyright (c) 2003-2005, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto.h" +#include "aes_i.h" + +/** + * Expand the cipher key into the decryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[]) +{ + int Nr = 10, i, j; + u32 temp; + + /* expand the cipher key: */ + rijndaelKeySetupEnc(rk, cipherKey); + /* invert the order of the round keys: */ + for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the + * first and the last: */ + for (i = 1; i < Nr; i++) { + rk += 4; + for (j = 0; j < 4; j++) { + rk[j] = TD0_(TE4((rk[j] >> 24) )) ^ + TD1_(TE4((rk[j] >> 16) & 0xff)) ^ + TD2_(TE4((rk[j] >> 8) & 0xff)) ^ + TD3_(TE4((rk[j] ) & 0xff)); + } + } +} + +void * aes_decrypt_init(const u8 *key, size_t len) +{ + u32 *rk; + if (len != 16) + return NULL; + rk = os_malloc(AES_PRIV_SIZE); + if (rk == NULL) + return NULL; + rijndaelKeySetupDec(rk, key); + return rk; +} + +static void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16]) +{ + u32 s0, s1, s2, s3, t0, t1, t2, t3; + const int Nr = 10; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(ct ) ^ rk[0]; + s1 = GETU32(ct + 4) ^ rk[1]; + s2 = GETU32(ct + 8) ^ rk[2]; + s3 = GETU32(ct + 12) ^ rk[3]; + +#define ROUND(i,d,s) \ +d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \ +d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \ +d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \ +d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3] + +#ifdef FULL_UNROLL + + ROUND(1,t,s); + ROUND(2,s,t); + ROUND(3,t,s); + ROUND(4,s,t); + ROUND(5,t,s); + ROUND(6,s,t); + ROUND(7,t,s); + ROUND(8,s,t); + ROUND(9,t,s); + + rk += Nr << 2; + +#else /* !FULL_UNROLL */ + + /* Nr - 1 full rounds: */ + r = Nr >> 1; + for (;;) { + ROUND(1,t,s); + rk += 8; + if (--r == 0) + break; + ROUND(0,s,t); + } + +#endif /* ?FULL_UNROLL */ + +#undef ROUND + + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0]; + PUTU32(pt , s0); + s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1]; + PUTU32(pt + 4, s1); + s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2]; + PUTU32(pt + 8, s2); + s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3]; + PUTU32(pt + 12, s3); +} + +void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) +{ + rijndaelDecrypt(ctx, crypt, plain); +} + + +void aes_decrypt_deinit(void *ctx) +{ + os_memset(ctx, 0, AES_PRIV_SIZE); + os_free(ctx); +} diff --git a/contrib/wpa/src/crypto/aes-internal-enc.c b/contrib/wpa/src/crypto/aes-internal-enc.c new file mode 100644 index 000000000000..2f198263bb84 --- /dev/null +++ b/contrib/wpa/src/crypto/aes-internal-enc.c @@ -0,0 +1,121 @@ +/* + * AES (Rijndael) cipher - encrypt + * + * Modifications to public domain implementation: + * - support only 128-bit keys + * - cleanup + * - use C pre-processor to make it easier to change S table access + * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at + * cost of reduced throughput (quite small difference on Pentium 4, + * 10-25% when using -O1 or -O2 optimization) + * + * Copyright (c) 2003-2005, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto.h" +#include "aes_i.h" + +void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16]) +{ + u32 s0, s1, s2, s3, t0, t1, t2, t3; + const int Nr = 10; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(pt ) ^ rk[0]; + s1 = GETU32(pt + 4) ^ rk[1]; + s2 = GETU32(pt + 8) ^ rk[2]; + s3 = GETU32(pt + 12) ^ rk[3]; + +#define ROUND(i,d,s) \ +d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ +d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ +d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ +d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] + +#ifdef FULL_UNROLL + + ROUND(1,t,s); + ROUND(2,s,t); + ROUND(3,t,s); + ROUND(4,s,t); + ROUND(5,t,s); + ROUND(6,s,t); + ROUND(7,t,s); + ROUND(8,s,t); + ROUND(9,t,s); + + rk += Nr << 2; + +#else /* !FULL_UNROLL */ + + /* Nr - 1 full rounds: */ + r = Nr >> 1; + for (;;) { + ROUND(1,t,s); + rk += 8; + if (--r == 0) + break; + ROUND(0,s,t); + } + +#endif /* ?FULL_UNROLL */ + +#undef ROUND + + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; + PUTU32(ct , s0); + s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; + PUTU32(ct + 4, s1); + s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; + PUTU32(ct + 8, s2); + s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; + PUTU32(ct + 12, s3); +} + + +void * aes_encrypt_init(const u8 *key, size_t len) +{ + u32 *rk; + if (len != 16) + return NULL; + rk = os_malloc(AES_PRIV_SIZE); + if (rk == NULL) + return NULL; + rijndaelKeySetupEnc(rk, key); + return rk; +} + + +void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) +{ + rijndaelEncrypt(ctx, plain, crypt); +} + + +void aes_encrypt_deinit(void *ctx) +{ + os_memset(ctx, 0, AES_PRIV_SIZE); + os_free(ctx); +} diff --git a/contrib/wpa/src/crypto/aes.c b/contrib/wpa/src/crypto/aes-internal.c similarity index 82% rename from contrib/wpa/src/crypto/aes.c rename to contrib/wpa/src/crypto/aes-internal.c index 8b8f2a04dee2..416122022066 100644 --- a/contrib/wpa/src/crypto/aes.c +++ b/contrib/wpa/src/crypto/aes-internal.c @@ -24,10 +24,8 @@ #include "includes.h" #include "common.h" - -#ifdef INTERNAL_AES - #include "crypto.h" +#include "aes_i.h" /* * rijndael-alg-fst.c @@ -55,9 +53,6 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* #define FULL_UNROLL */ -#define AES_SMALL_TABLES - /* Te0[x] = S [x].[02, 01, 01, 03]; @@ -73,7 +68,7 @@ Td3[x] = Si[x].[09, 0d, 0b, 0e]; Td4[x] = Si[x].[01, 01, 01, 01]; */ -static const u32 Te0[256] = { +const u32 Te0[256] = { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, @@ -140,7 +135,7 @@ static const u32 Te0[256] = { 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, }; #ifndef AES_SMALL_TABLES -static const u32 Te1[256] = { +const u32 Te1[256] = { 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, @@ -206,7 +201,7 @@ static const u32 Te1[256] = { 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, }; -static const u32 Te2[256] = { +const u32 Te2[256] = { 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, @@ -272,7 +267,7 @@ static const u32 Te2[256] = { 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, }; -static const u32 Te3[256] = { +const u32 Te3[256] = { 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, @@ -339,7 +334,7 @@ static const u32 Te3[256] = { 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, }; -static const u32 Te4[256] = { +const u32 Te4[256] = { 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, @@ -406,7 +401,7 @@ static const u32 Te4[256] = { 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, }; #endif /* AES_SMALL_TABLES */ -static const u32 Td0[256] = { +const u32 Td0[256] = { 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, @@ -473,7 +468,7 @@ static const u32 Td0[256] = { 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, }; #ifndef AES_SMALL_TABLES -static const u32 Td1[256] = { +const u32 Td1[256] = { 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, @@ -539,7 +534,7 @@ static const u32 Td1[256] = { 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, }; -static const u32 Td2[256] = { +const u32 Td2[256] = { 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, @@ -606,7 +601,7 @@ static const u32 Td2[256] = { 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, }; -static const u32 Td3[256] = { +const u32 Td3[256] = { 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, @@ -672,7 +667,7 @@ static const u32 Td3[256] = { 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, }; -static const u32 Td4[256] = { +const u32 Td4[256] = { 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, @@ -738,13 +733,13 @@ static const u32 Td4[256] = { 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, }; -static const u32 rcon[] = { +const u32 rcon[] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; #else /* AES_SMALL_TABLES */ -static const u8 Td4s[256] = { +const u8 Td4s[256] = { 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, @@ -778,95 +773,11 @@ static const u8 Td4s[256] = { 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, }; -static const u8 rcons[] = { +const u8 rcons[] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; #endif /* AES_SMALL_TABLES */ - - -#ifndef AES_SMALL_TABLES - -#define RCON(i) rcon[(i)] - -#define TE0(i) Te0[((i) >> 24) & 0xff] -#define TE1(i) Te1[((i) >> 16) & 0xff] -#define TE2(i) Te2[((i) >> 8) & 0xff] -#define TE3(i) Te3[(i) & 0xff] -#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000) -#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000) -#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00) -#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff) -#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000) -#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000) -#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00) -#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff) -#define TE4(i) (Te4[(i)] & 0x000000ff) - -#define TD0(i) Td0[((i) >> 24) & 0xff] -#define TD1(i) Td1[((i) >> 16) & 0xff] -#define TD2(i) Td2[((i) >> 8) & 0xff] -#define TD3(i) Td3[(i) & 0xff] -#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000) -#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000) -#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00) -#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff) -#define TD0_(i) Td0[(i) & 0xff] -#define TD1_(i) Td1[(i) & 0xff] -#define TD2_(i) Td2[(i) & 0xff] -#define TD3_(i) Td3[(i) & 0xff] - -#else /* AES_SMALL_TABLES */ - -#define RCON(i) (rcons[(i)] << 24) - -static inline u32 rotr(u32 val, int bits) -{ - return (val >> bits) | (val << (32 - bits)); -} - -#define TE0(i) Te0[((i) >> 24) & 0xff] -#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8) -#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16) -#define TE3(i) rotr(Te0[(i) & 0xff], 24) -#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) -#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) -#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) -#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) -#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000) -#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000) -#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00) -#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff) -#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff) - -#define TD0(i) Td0[((i) >> 24) & 0xff] -#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8) -#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16) -#define TD3(i) rotr(Td0[(i) & 0xff], 24) -#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24) -#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16) -#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8) -#define TD44(i) (Td4s[(i) & 0xff]) -#define TD0_(i) Td0[(i) & 0xff] -#define TD1_(i) rotr(Td0[(i) & 0xff], 8) -#define TD2_(i) rotr(Td0[(i) & 0xff], 16) -#define TD3_(i) rotr(Td0[(i) & 0xff], 24) - -#endif /* AES_SMALL_TABLES */ - -#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) - -#ifdef _MSC_VER -#define GETU32(p) SWAP(*((u32 *)(p))) -#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } -#else -#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ -((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) -#define PUTU32(ct, st) { \ -(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \ -(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } -#endif - /** * Expand the cipher key into the encryption key schedule. * @@ -892,236 +803,3 @@ void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]) rk += 4; } } - -#ifndef CONFIG_NO_AES_DECRYPT -/** - * Expand the cipher key into the decryption key schedule. - * - * @return the number of rounds for the given cipher key size. - */ -void rijndaelKeySetupDec(u32 rk[/*44*/], const u8 cipherKey[]) -{ - int Nr = 10, i, j; - u32 temp; - - /* expand the cipher key: */ - rijndaelKeySetupEnc(rk, cipherKey); - /* invert the order of the round keys: */ - for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { - temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; - temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; - temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; - temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; - } - /* apply the inverse MixColumn transform to all round keys but the - * first and the last: */ - for (i = 1; i < Nr; i++) { - rk += 4; - for (j = 0; j < 4; j++) { - rk[j] = TD0_(TE4((rk[j] >> 24) )) ^ - TD1_(TE4((rk[j] >> 16) & 0xff)) ^ - TD2_(TE4((rk[j] >> 8) & 0xff)) ^ - TD3_(TE4((rk[j] ) & 0xff)); - } - } -} -#endif /* CONFIG_NO_AES_DECRYPT */ - -#ifndef CONFIG_NO_AES_ENCRYPT -void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16]) -{ - u32 s0, s1, s2, s3, t0, t1, t2, t3; - const int Nr = 10; -#ifndef FULL_UNROLL - int r; -#endif /* ?FULL_UNROLL */ - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(pt ) ^ rk[0]; - s1 = GETU32(pt + 4) ^ rk[1]; - s2 = GETU32(pt + 8) ^ rk[2]; - s3 = GETU32(pt + 12) ^ rk[3]; - -#define ROUND(i,d,s) \ -d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ -d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ -d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ -d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] - -#ifdef FULL_UNROLL - - ROUND(1,t,s); - ROUND(2,s,t); - ROUND(3,t,s); - ROUND(4,s,t); - ROUND(5,t,s); - ROUND(6,s,t); - ROUND(7,t,s); - ROUND(8,s,t); - ROUND(9,t,s); - - rk += Nr << 2; - -#else /* !FULL_UNROLL */ - - /* Nr - 1 full rounds: */ - r = Nr >> 1; - for (;;) { - ROUND(1,t,s); - rk += 8; - if (--r == 0) - break; - ROUND(0,s,t); - } - -#endif /* ?FULL_UNROLL */ - -#undef ROUND - - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; - PUTU32(ct , s0); - s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; - PUTU32(ct + 4, s1); - s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; - PUTU32(ct + 8, s2); - s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; - PUTU32(ct + 12, s3); -} -#endif /* CONFIG_NO_AES_ENCRYPT */ - -void rijndaelDecrypt(const u32 rk[/*44*/], const u8 ct[16], u8 pt[16]) -{ - u32 s0, s1, s2, s3, t0, t1, t2, t3; - const int Nr = 10; -#ifndef FULL_UNROLL - int r; -#endif /* ?FULL_UNROLL */ - - /* - * map byte array block to cipher state - * and add initial round key: - */ - s0 = GETU32(ct ) ^ rk[0]; - s1 = GETU32(ct + 4) ^ rk[1]; - s2 = GETU32(ct + 8) ^ rk[2]; - s3 = GETU32(ct + 12) ^ rk[3]; - -#define ROUND(i,d,s) \ -d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \ -d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \ -d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \ -d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3] - -#ifdef FULL_UNROLL - - ROUND(1,t,s); - ROUND(2,s,t); - ROUND(3,t,s); - ROUND(4,s,t); - ROUND(5,t,s); - ROUND(6,s,t); - ROUND(7,t,s); - ROUND(8,s,t); - ROUND(9,t,s); - - rk += Nr << 2; - -#else /* !FULL_UNROLL */ - - /* Nr - 1 full rounds: */ - r = Nr >> 1; - for (;;) { - ROUND(1,t,s); - rk += 8; - if (--r == 0) - break; - ROUND(0,s,t); - } - -#endif /* ?FULL_UNROLL */ - -#undef ROUND - - /* - * apply last round and - * map cipher state to byte array block: - */ - s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0]; - PUTU32(pt , s0); - s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1]; - PUTU32(pt + 4, s1); - s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2]; - PUTU32(pt + 8, s2); - s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3]; - PUTU32(pt + 12, s3); -} - - - -/* Generic wrapper functions for AES functions */ - -#define AES_PRIV_SIZE (4 * 44) - -#ifndef CONFIG_NO_AES_ENCRYPT -void * aes_encrypt_init(const u8 *key, size_t len) -{ - u32 *rk; - if (len != 16) - return NULL; - rk = os_malloc(AES_PRIV_SIZE); - if (rk == NULL) - return NULL; - rijndaelKeySetupEnc(rk, key); - return rk; -} - - -void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) -{ - rijndaelEncrypt(ctx, plain, crypt); -} - - -void aes_encrypt_deinit(void *ctx) -{ - os_memset(ctx, 0, AES_PRIV_SIZE); - os_free(ctx); -} -#endif /* CONFIG_NO_AES_ENCRYPT */ - - -#ifndef CONFIG_NO_AES_DECRYPT -void * aes_decrypt_init(const u8 *key, size_t len) -{ - u32 *rk; - if (len != 16) - return NULL; - rk = os_malloc(AES_PRIV_SIZE); - if (rk == NULL) - return NULL; - rijndaelKeySetupDec(rk, key); - return rk; -} - - -void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) -{ - rijndaelDecrypt(ctx, crypt, plain); -} - - -void aes_decrypt_deinit(void *ctx) -{ - os_memset(ctx, 0, AES_PRIV_SIZE); - os_free(ctx); -} -#endif /* CONFIG_NO_AES_DECRYPT */ - -#endif /* INTERNAL_AES */ diff --git a/contrib/wpa/src/crypto/aes-omac1.c b/contrib/wpa/src/crypto/aes-omac1.c new file mode 100644 index 000000000000..f77529617a31 --- /dev/null +++ b/contrib/wpa/src/crypto/aes-omac1.c @@ -0,0 +1,124 @@ +/* + * One-key CBC MAC (OMAC1) hash with AES-128 + * + * Copyright (c) 2003-2007, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "aes.h" +#include "aes_wrap.h" + +static void gf_mulx(u8 *pad) +{ + int i, carry; + + carry = pad[0] & 0x80; + for (i = 0; i < AES_BLOCK_SIZE - 1; i++) + pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); + pad[AES_BLOCK_SIZE - 1] <<= 1; + if (carry) + pad[AES_BLOCK_SIZE - 1] ^= 0x87; +} + + +/** + * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 + * @key: 128-bit key for the hash operation + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) + * Returns: 0 on success, -1 on failure + * + * This is a mode for using block cipher (AES in this case) for authentication. + * OMAC1 was standardized with the name CMAC by NIST in a Special Publication + * (SP) 800-38B. + */ +int omac1_aes_128_vector(const u8 *key, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + void *ctx; + u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; + const u8 *pos, *end; + size_t i, e, left, total_len; + + ctx = aes_encrypt_init(key, 16); + if (ctx == NULL) + return -1; + os_memset(cbc, 0, AES_BLOCK_SIZE); + + total_len = 0; + for (e = 0; e < num_elem; e++) + total_len += len[e]; + left = total_len; + + e = 0; + pos = addr[0]; + end = pos + len[0]; + + while (left >= AES_BLOCK_SIZE) { + for (i = 0; i < AES_BLOCK_SIZE; i++) { + cbc[i] ^= *pos++; + if (pos >= end) { + e++; + pos = addr[e]; + end = pos + len[e]; + } + } + if (left > AES_BLOCK_SIZE) + aes_encrypt(ctx, cbc, cbc); + left -= AES_BLOCK_SIZE; + } + + os_memset(pad, 0, AES_BLOCK_SIZE); + aes_encrypt(ctx, pad, pad); + gf_mulx(pad); + + if (left || total_len == 0) { + for (i = 0; i < left; i++) { + cbc[i] ^= *pos++; + if (pos >= end) { + e++; + pos = addr[e]; + end = pos + len[e]; + } + } + cbc[left] ^= 0x80; + gf_mulx(pad); + } + + for (i = 0; i < AES_BLOCK_SIZE; i++) + pad[i] ^= cbc[i]; + aes_encrypt(ctx, pad, mac); + aes_encrypt_deinit(ctx); + return 0; +} + + +/** + * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) + * @key: 128-bit key for the hash operation + * @data: Data buffer for which a MAC is determined + * @data_len: Length of data buffer in bytes + * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) + * Returns: 0 on success, -1 on failure + * + * This is a mode for using block cipher (AES in this case) for authentication. + * OMAC1 was standardized with the name CMAC by NIST in a Special Publication + * (SP) 800-38B. + */ +int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) +{ + return omac1_aes_128_vector(key, 1, &data, &data_len, mac); +} diff --git a/contrib/wpa/src/crypto/aes-unwrap.c b/contrib/wpa/src/crypto/aes-unwrap.c new file mode 100644 index 000000000000..f233ffa4c04c --- /dev/null +++ b/contrib/wpa/src/crypto/aes-unwrap.c @@ -0,0 +1,79 @@ +/* + * AES key unwrap (128-bit KEK, RFC3394) + * + * Copyright (c) 2003-2007, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "aes.h" +#include "aes_wrap.h" + +/** + * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) + * @kek: Key encryption key (KEK) + * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 + * bytes + * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits + * @plain: Plaintext key, n * 64 bits + * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) + */ +int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain) +{ + u8 a[8], *r, b[16]; + int i, j; + void *ctx; + + /* 1) Initialize variables. */ + os_memcpy(a, cipher, 8); + r = plain; + os_memcpy(r, cipher + 8, 8 * n); + + ctx = aes_decrypt_init(kek, 16); + if (ctx == NULL) + return -1; + + /* 2) Compute intermediate values. + * For j = 5 to 0 + * For i = n to 1 + * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i + * A = MSB(64, B) + * R[i] = LSB(64, B) + */ + for (j = 5; j >= 0; j--) { + r = plain + (n - 1) * 8; + for (i = n; i >= 1; i--) { + os_memcpy(b, a, 8); + b[7] ^= n * j + i; + + os_memcpy(b + 8, r, 8); + aes_decrypt(ctx, b, b); + os_memcpy(a, b, 8); + os_memcpy(r, b + 8, 8); + r -= 8; + } + } + aes_decrypt_deinit(ctx); + + /* 3) Output results. + * + * These are already in @plain due to the location of temporary + * variables. Just verify that the IV matches with the expected value. + */ + for (i = 0; i < 8; i++) { + if (a[i] != 0xa6) + return -1; + } + + return 0; +} diff --git a/contrib/wpa/src/crypto/aes-wrap.c b/contrib/wpa/src/crypto/aes-wrap.c new file mode 100644 index 000000000000..28d0c89e88f0 --- /dev/null +++ b/contrib/wpa/src/crypto/aes-wrap.c @@ -0,0 +1,76 @@ +/* + * AES Key Wrap Algorithm (128-bit KEK) (RFC3394) + * + * Copyright (c) 2003-2007, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "aes.h" +#include "aes_wrap.h" + +/** + * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) + * @kek: 16-octet Key encryption key (KEK) + * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 + * bytes + * @plain: Plaintext key to be wrapped, n * 64 bits + * @cipher: Wrapped key, (n + 1) * 64 bits + * Returns: 0 on success, -1 on failure + */ +int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher) +{ + u8 *a, *r, b[16]; + int i, j; + void *ctx; + + a = cipher; + r = cipher + 8; + + /* 1) Initialize variables. */ + os_memset(a, 0xa6, 8); + os_memcpy(r, plain, 8 * n); + + ctx = aes_encrypt_init(kek, 16); + if (ctx == NULL) + return -1; + + /* 2) Calculate intermediate values. + * For j = 0 to 5 + * For i=1 to n + * B = AES(K, A | R[i]) + * A = MSB(64, B) ^ t where t = (n*j)+i + * R[i] = LSB(64, B) + */ + for (j = 0; j <= 5; j++) { + r = cipher + 8; + for (i = 1; i <= n; i++) { + os_memcpy(b, a, 8); + os_memcpy(b + 8, r, 8); + aes_encrypt(ctx, b, b); + os_memcpy(a, b, 8); + a[7] ^= n * j + i; + os_memcpy(r, b + 8, 8); + r += 8; + } + } + aes_encrypt_deinit(ctx); + + /* 3) Output the results. + * + * These are already in @cipher due to the location of temporary + * variables. + */ + + return 0; +} diff --git a/contrib/wpa/src/crypto/aes.h b/contrib/wpa/src/crypto/aes.h index 6b9f4147afb1..ba384a9dae37 100644 --- a/contrib/wpa/src/crypto/aes.h +++ b/contrib/wpa/src/crypto/aes.h @@ -15,6 +15,8 @@ #ifndef AES_H #define AES_H +#define AES_BLOCK_SIZE 16 + void * aes_encrypt_init(const u8 *key, size_t len); void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); void aes_encrypt_deinit(void *ctx); diff --git a/contrib/wpa/src/crypto/aes_i.h b/contrib/wpa/src/crypto/aes_i.h new file mode 100644 index 000000000000..6b40bc781651 --- /dev/null +++ b/contrib/wpa/src/crypto/aes_i.h @@ -0,0 +1,122 @@ +/* + * AES (Rijndael) cipher + * Copyright (c) 2003-2005, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef AES_I_H +#define AES_I_H + +#include "aes.h" + +/* #define FULL_UNROLL */ +#define AES_SMALL_TABLES + +extern const u32 Te0[256]; +extern const u32 Te1[256]; +extern const u32 Te2[256]; +extern const u32 Te3[256]; +extern const u32 Te4[256]; +extern const u32 Td0[256]; +extern const u32 Td1[256]; +extern const u32 Td2[256]; +extern const u32 Td3[256]; +extern const u32 Td4[256]; +extern const u32 rcon[10]; +extern const u8 Td4s[256]; +extern const u8 rcons[10]; + +#ifndef AES_SMALL_TABLES + +#define RCON(i) rcon[(i)] + +#define TE0(i) Te0[((i) >> 24) & 0xff] +#define TE1(i) Te1[((i) >> 16) & 0xff] +#define TE2(i) Te2[((i) >> 8) & 0xff] +#define TE3(i) Te3[(i) & 0xff] +#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000) +#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000) +#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00) +#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff) +#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000) +#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000) +#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00) +#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff) +#define TE4(i) (Te4[(i)] & 0x000000ff) + +#define TD0(i) Td0[((i) >> 24) & 0xff] +#define TD1(i) Td1[((i) >> 16) & 0xff] +#define TD2(i) Td2[((i) >> 8) & 0xff] +#define TD3(i) Td3[(i) & 0xff] +#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000) +#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000) +#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00) +#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff) +#define TD0_(i) Td0[(i) & 0xff] +#define TD1_(i) Td1[(i) & 0xff] +#define TD2_(i) Td2[(i) & 0xff] +#define TD3_(i) Td3[(i) & 0xff] + +#else /* AES_SMALL_TABLES */ + +#define RCON(i) (rcons[(i)] << 24) + +static inline u32 rotr(u32 val, int bits) +{ + return (val >> bits) | (val << (32 - bits)); +} + +#define TE0(i) Te0[((i) >> 24) & 0xff] +#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8) +#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16) +#define TE3(i) rotr(Te0[(i) & 0xff], 24) +#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) +#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) +#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) +#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) +#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000) +#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000) +#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00) +#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff) +#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff) + +#define TD0(i) Td0[((i) >> 24) & 0xff] +#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8) +#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16) +#define TD3(i) rotr(Td0[(i) & 0xff], 24) +#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24) +#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16) +#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8) +#define TD44(i) (Td4s[(i) & 0xff]) +#define TD0_(i) Td0[(i) & 0xff] +#define TD1_(i) rotr(Td0[(i) & 0xff], 8) +#define TD2_(i) rotr(Td0[(i) & 0xff], 16) +#define TD3_(i) rotr(Td0[(i) & 0xff], 24) + +#endif /* AES_SMALL_TABLES */ + +#ifdef _MSC_VER +#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +#define GETU32(p) SWAP(*((u32 *)(p))) +#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } +#else +#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ +((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +#define PUTU32(ct, st) { \ +(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \ +(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } +#endif + +#define AES_PRIV_SIZE (4 * 44) + +void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]); + +#endif /* AES_I_H */ diff --git a/contrib/wpa/src/crypto/aes_wrap.c b/contrib/wpa/src/crypto/aes_wrap.c deleted file mode 100644 index b1448b0d9a8d..000000000000 --- a/contrib/wpa/src/crypto/aes_wrap.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * AES-based functions - * - * - AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * - One-Key CBC MAC (OMAC1, i.e., CMAC) hash with AES-128 - * - AES-128 CTR mode encryption - * - AES-128 EAX mode encryption/decryption - * - AES-128 CBC - * - * Copyright (c) 2003-2007, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "aes_wrap.h" -#include "crypto.h" - -#ifndef CONFIG_NO_AES_WRAP - -/** - * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * @kek: 16-octet Key encryption key (KEK) - * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 - * bytes - * @plain: Plaintext key to be wrapped, n * 64 bits - * @cipher: Wrapped key, (n + 1) * 64 bits - * Returns: 0 on success, -1 on failure - */ -int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher) -{ - u8 *a, *r, b[16]; - int i, j; - void *ctx; - - a = cipher; - r = cipher + 8; - - /* 1) Initialize variables. */ - os_memset(a, 0xa6, 8); - os_memcpy(r, plain, 8 * n); - - ctx = aes_encrypt_init(kek, 16); - if (ctx == NULL) - return -1; - - /* 2) Calculate intermediate values. - * For j = 0 to 5 - * For i=1 to n - * B = AES(K, A | R[i]) - * A = MSB(64, B) ^ t where t = (n*j)+i - * R[i] = LSB(64, B) - */ - for (j = 0; j <= 5; j++) { - r = cipher + 8; - for (i = 1; i <= n; i++) { - os_memcpy(b, a, 8); - os_memcpy(b + 8, r, 8); - aes_encrypt(ctx, b, b); - os_memcpy(a, b, 8); - a[7] ^= n * j + i; - os_memcpy(r, b + 8, 8); - r += 8; - } - } - aes_encrypt_deinit(ctx); - - /* 3) Output the results. - * - * These are already in @cipher due to the location of temporary - * variables. - */ - - return 0; -} - -#endif /* CONFIG_NO_AES_WRAP */ - - -#ifndef CONFIG_NO_AES_UNWRAP - -/** - * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * @kek: Key encryption key (KEK) - * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 - * bytes - * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits - * @plain: Plaintext key, n * 64 bits - * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) - */ -int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain) -{ - u8 a[8], *r, b[16]; - int i, j; - void *ctx; - - /* 1) Initialize variables. */ - os_memcpy(a, cipher, 8); - r = plain; - os_memcpy(r, cipher + 8, 8 * n); - - ctx = aes_decrypt_init(kek, 16); - if (ctx == NULL) - return -1; - - /* 2) Compute intermediate values. - * For j = 5 to 0 - * For i = n to 1 - * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i - * A = MSB(64, B) - * R[i] = LSB(64, B) - */ - for (j = 5; j >= 0; j--) { - r = plain + (n - 1) * 8; - for (i = n; i >= 1; i--) { - os_memcpy(b, a, 8); - b[7] ^= n * j + i; - - os_memcpy(b + 8, r, 8); - aes_decrypt(ctx, b, b); - os_memcpy(a, b, 8); - os_memcpy(r, b + 8, 8); - r -= 8; - } - } - aes_decrypt_deinit(ctx); - - /* 3) Output results. - * - * These are already in @plain due to the location of temporary - * variables. Just verify that the IV matches with the expected value. - */ - for (i = 0; i < 8; i++) { - if (a[i] != 0xa6) - return -1; - } - - return 0; -} - -#endif /* CONFIG_NO_AES_UNWRAP */ - - -#define BLOCK_SIZE 16 - -#ifndef CONFIG_NO_AES_OMAC1 - -static void gf_mulx(u8 *pad) -{ - int i, carry; - - carry = pad[0] & 0x80; - for (i = 0; i < BLOCK_SIZE - 1; i++) - pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); - pad[BLOCK_SIZE - 1] <<= 1; - if (carry) - pad[BLOCK_SIZE - 1] ^= 0x87; -} - - -/** - * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 - * @key: 128-bit key for the hash operation - * @num_elem: Number of elements in the data vector - * @addr: Pointers to the data areas - * @len: Lengths of the data blocks - * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) - * Returns: 0 on success, -1 on failure - * - * This is a mode for using block cipher (AES in this case) for authentication. - * OMAC1 was standardized with the name CMAC by NIST in a Special Publication - * (SP) 800-38B. - */ -int omac1_aes_128_vector(const u8 *key, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) -{ - void *ctx; - u8 cbc[BLOCK_SIZE], pad[BLOCK_SIZE]; - const u8 *pos, *end; - size_t i, e, left, total_len; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memset(cbc, 0, BLOCK_SIZE); - - total_len = 0; - for (e = 0; e < num_elem; e++) - total_len += len[e]; - left = total_len; - - e = 0; - pos = addr[0]; - end = pos + len[0]; - - while (left >= BLOCK_SIZE) { - for (i = 0; i < BLOCK_SIZE; i++) { - cbc[i] ^= *pos++; - if (pos >= end) { - e++; - pos = addr[e]; - end = pos + len[e]; - } - } - if (left > BLOCK_SIZE) - aes_encrypt(ctx, cbc, cbc); - left -= BLOCK_SIZE; - } - - os_memset(pad, 0, BLOCK_SIZE); - aes_encrypt(ctx, pad, pad); - gf_mulx(pad); - - if (left || total_len == 0) { - for (i = 0; i < left; i++) { - cbc[i] ^= *pos++; - if (pos >= end) { - e++; - pos = addr[e]; - end = pos + len[e]; - } - } - cbc[left] ^= 0x80; - gf_mulx(pad); - } - - for (i = 0; i < BLOCK_SIZE; i++) - pad[i] ^= cbc[i]; - aes_encrypt(ctx, pad, mac); - aes_encrypt_deinit(ctx); - return 0; -} - - -/** - * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) - * @key: 128-bit key for the hash operation - * @data: Data buffer for which a MAC is determined - * @data_len: Length of data buffer in bytes - * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) - * Returns: 0 on success, -1 on failure - * - * This is a mode for using block cipher (AES in this case) for authentication. - * OMAC1 was standardized with the name CMAC by NIST in a Special Publication - * (SP) 800-38B. - */ -int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) -{ - return omac1_aes_128_vector(key, 1, &data, &data_len, mac); -} - -#endif /* CONFIG_NO_AES_OMAC1 */ - - -#ifndef CONFIG_NO_AES_ENCRYPT_BLOCK -/** - * aes_128_encrypt_block - Perform one AES 128-bit block operation - * @key: Key for AES - * @in: Input data (16 bytes) - * @out: Output of the AES block operation (16 bytes) - * Returns: 0 on success, -1 on failure - */ -int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out) -{ - void *ctx; - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - aes_encrypt(ctx, in, out); - aes_encrypt_deinit(ctx); - return 0; -} -#endif /* CONFIG_NO_AES_ENCRYPT_BLOCK */ - - -#ifndef CONFIG_NO_AES_CTR - -/** - * aes_128_ctr_encrypt - AES-128 CTR mode encryption - * @key: Key for encryption (16 bytes) - * @nonce: Nonce for counter mode (16 bytes) - * @data: Data to encrypt in-place - * @data_len: Length of data in bytes - * Returns: 0 on success, -1 on failure - */ -int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, - u8 *data, size_t data_len) -{ - void *ctx; - size_t j, len, left = data_len; - int i; - u8 *pos = data; - u8 counter[BLOCK_SIZE], buf[BLOCK_SIZE]; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(counter, nonce, BLOCK_SIZE); - - while (left > 0) { - aes_encrypt(ctx, counter, buf); - - len = (left < BLOCK_SIZE) ? left : BLOCK_SIZE; - for (j = 0; j < len; j++) - pos[j] ^= buf[j]; - pos += len; - left -= len; - - for (i = BLOCK_SIZE - 1; i >= 0; i--) { - counter[i]++; - if (counter[i]) - break; - } - } - aes_encrypt_deinit(ctx); - return 0; -} - -#endif /* CONFIG_NO_AES_CTR */ - - -#ifndef CONFIG_NO_AES_EAX - -/** - * aes_128_eax_encrypt - AES-128 EAX mode encryption - * @key: Key for encryption (16 bytes) - * @nonce: Nonce for counter mode - * @nonce_len: Nonce length in bytes - * @hdr: Header data to be authenticity protected - * @hdr_len: Length of the header data bytes - * @data: Data to encrypt in-place - * @data_len: Length of data in bytes - * @tag: 16-byte tag value - * Returns: 0 on success, -1 on failure - */ -int aes_128_eax_encrypt(const u8 *key, const u8 *nonce, size_t nonce_len, - const u8 *hdr, size_t hdr_len, - u8 *data, size_t data_len, u8 *tag) -{ - u8 *buf; - size_t buf_len; - u8 nonce_mac[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[BLOCK_SIZE]; - int i, ret = -1; - - if (nonce_len > data_len) - buf_len = nonce_len; - else - buf_len = data_len; - if (hdr_len > buf_len) - buf_len = hdr_len; - buf_len += 16; - - buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - - os_memset(buf, 0, 15); - - buf[15] = 0; - os_memcpy(buf + 16, nonce, nonce_len); - if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) - goto fail; - - buf[15] = 1; - os_memcpy(buf + 16, hdr, hdr_len); - if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) - goto fail; - - if (aes_128_ctr_encrypt(key, nonce_mac, data, data_len)) - goto fail; - buf[15] = 2; - os_memcpy(buf + 16, data, data_len); - if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) - goto fail; - - for (i = 0; i < BLOCK_SIZE; i++) - tag[i] = nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i]; - - ret = 0; -fail: - os_free(buf); - - return ret; -} - - -/** - * aes_128_eax_decrypt - AES-128 EAX mode decryption - * @key: Key for decryption (16 bytes) - * @nonce: Nonce for counter mode - * @nonce_len: Nonce length in bytes - * @hdr: Header data to be authenticity protected - * @hdr_len: Length of the header data bytes - * @data: Data to encrypt in-place - * @data_len: Length of data in bytes - * @tag: 16-byte tag value - * Returns: 0 on success, -1 on failure, -2 if tag does not match - */ -int aes_128_eax_decrypt(const u8 *key, const u8 *nonce, size_t nonce_len, - const u8 *hdr, size_t hdr_len, - u8 *data, size_t data_len, const u8 *tag) -{ - u8 *buf; - size_t buf_len; - u8 nonce_mac[BLOCK_SIZE], hdr_mac[BLOCK_SIZE], data_mac[BLOCK_SIZE]; - int i; - - if (nonce_len > data_len) - buf_len = nonce_len; - else - buf_len = data_len; - if (hdr_len > buf_len) - buf_len = hdr_len; - buf_len += 16; - - buf = os_malloc(buf_len); - if (buf == NULL) - return -1; - - os_memset(buf, 0, 15); - - buf[15] = 0; - os_memcpy(buf + 16, nonce, nonce_len); - if (omac1_aes_128(key, buf, 16 + nonce_len, nonce_mac)) { - os_free(buf); - return -1; - } - - buf[15] = 1; - os_memcpy(buf + 16, hdr, hdr_len); - if (omac1_aes_128(key, buf, 16 + hdr_len, hdr_mac)) { - os_free(buf); - return -1; - } - - buf[15] = 2; - os_memcpy(buf + 16, data, data_len); - if (omac1_aes_128(key, buf, 16 + data_len, data_mac)) { - os_free(buf); - return -1; - } - - os_free(buf); - - for (i = 0; i < BLOCK_SIZE; i++) { - if (tag[i] != (nonce_mac[i] ^ data_mac[i] ^ hdr_mac[i])) - return -2; - } - - return aes_128_ctr_encrypt(key, nonce_mac, data, data_len); -} - -#endif /* CONFIG_NO_AES_EAX */ - - -#ifndef CONFIG_NO_AES_CBC - -/** - * aes_128_cbc_encrypt - AES-128 CBC encryption - * @key: Encryption key - * @iv: Encryption IV for CBC mode (16 bytes) - * @data: Data to encrypt in-place - * @data_len: Length of data in bytes (must be divisible by 16) - * Returns: 0 on success, -1 on failure - */ -int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) -{ - void *ctx; - u8 cbc[BLOCK_SIZE]; - u8 *pos = data; - int i, j, blocks; - - ctx = aes_encrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(cbc, iv, BLOCK_SIZE); - - blocks = data_len / BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - for (j = 0; j < BLOCK_SIZE; j++) - cbc[j] ^= pos[j]; - aes_encrypt(ctx, cbc, cbc); - os_memcpy(pos, cbc, BLOCK_SIZE); - pos += BLOCK_SIZE; - } - aes_encrypt_deinit(ctx); - return 0; -} - - -/** - * aes_128_cbc_decrypt - AES-128 CBC decryption - * @key: Decryption key - * @iv: Decryption IV for CBC mode (16 bytes) - * @data: Data to decrypt in-place - * @data_len: Length of data in bytes (must be divisible by 16) - * Returns: 0 on success, -1 on failure - */ -int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) -{ - void *ctx; - u8 cbc[BLOCK_SIZE], tmp[BLOCK_SIZE]; - u8 *pos = data; - int i, j, blocks; - - ctx = aes_decrypt_init(key, 16); - if (ctx == NULL) - return -1; - os_memcpy(cbc, iv, BLOCK_SIZE); - - blocks = data_len / BLOCK_SIZE; - for (i = 0; i < blocks; i++) { - os_memcpy(tmp, pos, BLOCK_SIZE); - aes_decrypt(ctx, pos, pos); - for (j = 0; j < BLOCK_SIZE; j++) - pos[j] ^= cbc[j]; - os_memcpy(cbc, tmp, BLOCK_SIZE); - pos += BLOCK_SIZE; - } - aes_decrypt_deinit(ctx); - return 0; -} - -#endif /* CONFIG_NO_AES_CBC */ diff --git a/contrib/wpa/src/crypto/crypto.h b/contrib/wpa/src/crypto/crypto.h index a5129bbd050a..587b5a95747f 100644 --- a/contrib/wpa/src/crypto/crypto.h +++ b/contrib/wpa/src/crypto/crypto.h @@ -1,6 +1,6 @@ /* * WPA Supplicant / wrapper functions for crypto libraries - * Copyright (c) 2004-2007, Jouni Malinen + * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -33,8 +33,9 @@ * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure */ -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); +int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); /** * md5_vector - MD5 hash for data vector @@ -42,8 +43,25 @@ void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure */ -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); + +#ifdef CONFIG_FIPS +/** + * md5_vector_non_fips_allow - MD5 hash for data vector (non-FIPS use allowed) + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure + */ +int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac); +#else /* CONFIG_FIPS */ +#define md5_vector_non_fips_allow md5_vector +#endif /* CONFIG_FIPS */ + /** * sha1_vector - SHA-1 hash for data vector @@ -51,9 +69,10 @@ void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure */ -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac); +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac); /** * fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF @@ -76,9 +95,10 @@ int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure */ -void sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac); +int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac); /** * des_encrypt - Encrypt one block with DES @@ -275,6 +295,7 @@ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len); * crypto_private_key_import - Import an RSA private key * @key: Key buffer (DER encoded RSA private key) * @len: Key buffer length in bytes + * @passwd: Key encryption password or %NULL if key is not encrypted * Returns: Pointer to the private key or %NULL on failure * * This function is only used with internal TLSv1 implementation @@ -282,7 +303,8 @@ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len); * to implement this. */ struct crypto_private_key * crypto_private_key_import(const u8 *key, - size_t len); + size_t len, + const char *passwd); /** * crypto_public_key_from_cert - Import an RSA public key from a certificate @@ -428,4 +450,20 @@ int __must_check crypto_mod_exp(const u8 *base, size_t base_len, const u8 *modulus, size_t modulus_len, u8 *result, size_t *result_len); +/** + * rc4_skip - XOR RC4 stream to given data with skip-stream-start + * @key: RC4 key + * @keylen: RC4 key length + * @skip: number of bytes to skip from the beginning of the RC4 stream + * @data: data to be XOR'ed with RC4 stream + * @data_len: buf length + * Returns: 0 on success, -1 on failure + * + * Generate RC4 pseudo random stream for the given key, skip beginning of the + * stream, and XOR the end result with the data buffer to perform RC4 + * encryption/decryption. + */ +int rc4_skip(const u8 *key, size_t keylen, size_t skip, + u8 *data, size_t data_len); + #endif /* CRYPTO_H */ diff --git a/contrib/wpa/src/crypto/crypto_cryptoapi.c b/contrib/wpa/src/crypto/crypto_cryptoapi.c index 45333dd2e396..2a8d2001b173 100644 --- a/contrib/wpa/src/crypto/crypto_cryptoapi.c +++ b/contrib/wpa/src/crypto/crypto_cryptoapi.c @@ -33,7 +33,6 @@ L"Microsoft Enhanced RSA and AES Cryptographic Provider (Prototype)" #define CALG_HMAC (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_HMAC) #endif -#ifdef CONFIG_TLS_INTERNAL #ifdef __MINGW32_VERSION /* * MinGW does not yet include all the needed definitions for CryptoAPI, so @@ -83,7 +82,6 @@ static int mingw_load_crypto_func(void) } #endif /* __MINGW32_VERSION */ -#endif /* CONFIG_TLS_INTERNAL */ static void cryptoapi_report_error(const char *msg) @@ -152,9 +150,9 @@ int cryptoapi_hash_vector(ALG_ID alg, size_t hash_len, size_t num_elem, } -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { - cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac); + return cryptoapi_hash_vector(CALG_MD4, 16, num_elem, addr, len, mac); } @@ -223,16 +221,15 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) } -#ifdef EAP_TLS_FUNCS -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { - cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac); + return cryptoapi_hash_vector(CALG_MD5, 16, num_elem, addr, len, mac); } -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { - cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac); + return cryptoapi_hash_vector(CALG_SHA, 20, num_elem, addr, len, mac); } @@ -349,7 +346,6 @@ void aes_decrypt_deinit(void *ctx) aes_encrypt_deinit(ctx); } -#ifdef CONFIG_TLS_INTERNAL struct crypto_hash { enum crypto_hash_alg alg; @@ -657,7 +653,8 @@ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) struct crypto_private_key * crypto_private_key_import(const u8 *key, - size_t len) + size_t len, + const char *passwd) { /* TODO */ return NULL; @@ -781,6 +778,12 @@ void crypto_global_deinit(void) { } -#endif /* CONFIG_TLS_INTERNAL */ -#endif /* EAP_TLS_FUNCS */ +int crypto_mod_exp(const u8 *base, size_t base_len, + const u8 *power, size_t power_len, + const u8 *modulus, size_t modulus_len, + u8 *result, size_t *result_len) +{ + /* TODO */ + return -1; +} diff --git a/contrib/wpa/src/crypto/crypto_gnutls.c b/contrib/wpa/src/crypto/crypto_gnutls.c index 8f8611c0fb33..0998cca54672 100644 --- a/contrib/wpa/src/crypto/crypto_gnutls.c +++ b/contrib/wpa/src/crypto/crypto_gnutls.c @@ -18,20 +18,21 @@ #include "common.h" #include "crypto.h" -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { gcry_md_hd_t hd; unsigned char *p; size_t i; if (gcry_md_open(&hd, GCRY_MD_MD4, 0) != GPG_ERR_NO_ERROR) - return; + return -1; for (i = 0; i < num_elem; i++) gcry_md_write(hd, addr[i], len[i]); p = gcry_md_read(hd, GCRY_MD_MD4); if (p) memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD4)); gcry_md_close(hd); + return 0; } @@ -57,49 +58,42 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) } -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { gcry_md_hd_t hd; unsigned char *p; size_t i; if (gcry_md_open(&hd, GCRY_MD_MD5, 0) != GPG_ERR_NO_ERROR) - return; + return -1; for (i = 0; i < num_elem; i++) gcry_md_write(hd, addr[i], len[i]); p = gcry_md_read(hd, GCRY_MD_MD5); if (p) memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_MD5)); gcry_md_close(hd); + return 0; } -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { gcry_md_hd_t hd; unsigned char *p; size_t i; if (gcry_md_open(&hd, GCRY_MD_SHA1, 0) != GPG_ERR_NO_ERROR) - return; + return -1; for (i = 0; i < num_elem; i++) gcry_md_write(hd, addr[i], len[i]); p = gcry_md_read(hd, GCRY_MD_SHA1); if (p) memcpy(mac, p, gcry_md_get_algo_dlen(GCRY_MD_SHA1)); gcry_md_close(hd); + return 0; } -#ifndef CONFIG_NO_FIPS186_2_PRF -int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) -{ - /* FIX: how to do this with libgcrypt? */ - return -1; -} -#endif /* CONFIG_NO_FIPS186_2_PRF */ - - void * aes_encrypt_init(const u8 *key, size_t len) { gcry_cipher_hd_t hd; diff --git a/contrib/wpa/src/crypto/crypto_internal-cipher.c b/contrib/wpa/src/crypto/crypto_internal-cipher.c new file mode 100644 index 000000000000..75134f09a403 --- /dev/null +++ b/contrib/wpa/src/crypto/crypto_internal-cipher.c @@ -0,0 +1,256 @@ +/* + * Crypto wrapper for internal crypto implementation - Cipher wrappers + * Copyright (c) 2006-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto.h" +#include "aes.h" +#include "des_i.h" + + +struct crypto_cipher { + enum crypto_cipher_alg alg; + union { + struct { + size_t used_bytes; + u8 key[16]; + size_t keylen; + } rc4; + struct { + u8 cbc[32]; + size_t block_size; + void *ctx_enc; + void *ctx_dec; + } aes; + struct { + struct des3_key_s key; + u8 cbc[8]; + } des3; + struct { + u32 ek[32]; + u32 dk[32]; + u8 cbc[8]; + } des; + } u; +}; + + +struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, + const u8 *iv, const u8 *key, + size_t key_len) +{ + struct crypto_cipher *ctx; + + ctx = os_zalloc(sizeof(*ctx)); + if (ctx == NULL) + return NULL; + + ctx->alg = alg; + + switch (alg) { + case CRYPTO_CIPHER_ALG_RC4: + if (key_len > sizeof(ctx->u.rc4.key)) { + os_free(ctx); + return NULL; + } + ctx->u.rc4.keylen = key_len; + os_memcpy(ctx->u.rc4.key, key, key_len); + break; + case CRYPTO_CIPHER_ALG_AES: + if (key_len > sizeof(ctx->u.aes.cbc)) { + os_free(ctx); + return NULL; + } + ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len); + if (ctx->u.aes.ctx_enc == NULL) { + os_free(ctx); + return NULL; + } + ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len); + if (ctx->u.aes.ctx_dec == NULL) { + aes_encrypt_deinit(ctx->u.aes.ctx_enc); + os_free(ctx); + return NULL; + } + ctx->u.aes.block_size = key_len; + os_memcpy(ctx->u.aes.cbc, iv, ctx->u.aes.block_size); + break; + case CRYPTO_CIPHER_ALG_3DES: + if (key_len != 24) { + os_free(ctx); + return NULL; + } + des3_key_setup(key, &ctx->u.des3.key); + os_memcpy(ctx->u.des3.cbc, iv, 8); + break; + case CRYPTO_CIPHER_ALG_DES: + if (key_len != 8) { + os_free(ctx); + return NULL; + } + des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk); + os_memcpy(ctx->u.des.cbc, iv, 8); + break; + default: + os_free(ctx); + return NULL; + } + + return ctx; +} + + +int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, + u8 *crypt, size_t len) +{ + size_t i, j, blocks; + + switch (ctx->alg) { + case CRYPTO_CIPHER_ALG_RC4: + if (plain != crypt) + os_memcpy(crypt, plain, len); + rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, + ctx->u.rc4.used_bytes, crypt, len); + ctx->u.rc4.used_bytes += len; + break; + case CRYPTO_CIPHER_ALG_AES: + if (len % ctx->u.aes.block_size) + return -1; + blocks = len / ctx->u.aes.block_size; + for (i = 0; i < blocks; i++) { + for (j = 0; j < ctx->u.aes.block_size; j++) + ctx->u.aes.cbc[j] ^= plain[j]; + aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc, + ctx->u.aes.cbc); + os_memcpy(crypt, ctx->u.aes.cbc, + ctx->u.aes.block_size); + plain += ctx->u.aes.block_size; + crypt += ctx->u.aes.block_size; + } + break; + case CRYPTO_CIPHER_ALG_3DES: + if (len % 8) + return -1; + blocks = len / 8; + for (i = 0; i < blocks; i++) { + for (j = 0; j < 8; j++) + ctx->u.des3.cbc[j] ^= plain[j]; + des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key, + ctx->u.des3.cbc); + os_memcpy(crypt, ctx->u.des3.cbc, 8); + plain += 8; + crypt += 8; + } + break; + case CRYPTO_CIPHER_ALG_DES: + if (len % 8) + return -1; + blocks = len / 8; + for (i = 0; i < blocks; i++) { + for (j = 0; j < 8; j++) + ctx->u.des3.cbc[j] ^= plain[j]; + des_block_encrypt(ctx->u.des.cbc, ctx->u.des.ek, + ctx->u.des.cbc); + os_memcpy(crypt, ctx->u.des.cbc, 8); + plain += 8; + crypt += 8; + } + break; + default: + return -1; + } + + return 0; +} + + +int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, + u8 *plain, size_t len) +{ + size_t i, j, blocks; + u8 tmp[32]; + + switch (ctx->alg) { + case CRYPTO_CIPHER_ALG_RC4: + if (plain != crypt) + os_memcpy(plain, crypt, len); + rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, + ctx->u.rc4.used_bytes, plain, len); + ctx->u.rc4.used_bytes += len; + break; + case CRYPTO_CIPHER_ALG_AES: + if (len % ctx->u.aes.block_size) + return -1; + blocks = len / ctx->u.aes.block_size; + for (i = 0; i < blocks; i++) { + os_memcpy(tmp, crypt, ctx->u.aes.block_size); + aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain); + for (j = 0; j < ctx->u.aes.block_size; j++) + plain[j] ^= ctx->u.aes.cbc[j]; + os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size); + plain += ctx->u.aes.block_size; + crypt += ctx->u.aes.block_size; + } + break; + case CRYPTO_CIPHER_ALG_3DES: + if (len % 8) + return -1; + blocks = len / 8; + for (i = 0; i < blocks; i++) { + os_memcpy(tmp, crypt, 8); + des3_decrypt(crypt, &ctx->u.des3.key, plain); + for (j = 0; j < 8; j++) + plain[j] ^= ctx->u.des3.cbc[j]; + os_memcpy(ctx->u.des3.cbc, tmp, 8); + plain += 8; + crypt += 8; + } + break; + case CRYPTO_CIPHER_ALG_DES: + if (len % 8) + return -1; + blocks = len / 8; + for (i = 0; i < blocks; i++) { + os_memcpy(tmp, crypt, 8); + des_block_decrypt(crypt, ctx->u.des.dk, plain); + for (j = 0; j < 8; j++) + plain[j] ^= ctx->u.des.cbc[j]; + os_memcpy(ctx->u.des.cbc, tmp, 8); + plain += 8; + crypt += 8; + } + break; + default: + return -1; + } + + return 0; +} + + +void crypto_cipher_deinit(struct crypto_cipher *ctx) +{ + switch (ctx->alg) { + case CRYPTO_CIPHER_ALG_AES: + aes_encrypt_deinit(ctx->u.aes.ctx_enc); + aes_decrypt_deinit(ctx->u.aes.ctx_dec); + break; + case CRYPTO_CIPHER_ALG_3DES: + break; + default: + break; + } + os_free(ctx); +} diff --git a/contrib/wpa/src/crypto/crypto_internal-modexp.c b/contrib/wpa/src/crypto/crypto_internal-modexp.c new file mode 100644 index 000000000000..3124742e87cd --- /dev/null +++ b/contrib/wpa/src/crypto/crypto_internal-modexp.c @@ -0,0 +1,55 @@ +/* + * Crypto wrapper for internal crypto implementation - modexp + * Copyright (c) 2006-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "tls/bignum.h" +#include "crypto.h" + + +int crypto_mod_exp(const u8 *base, size_t base_len, + const u8 *power, size_t power_len, + const u8 *modulus, size_t modulus_len, + u8 *result, size_t *result_len) +{ + struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result; + int ret = -1; + + bn_base = bignum_init(); + bn_exp = bignum_init(); + bn_modulus = bignum_init(); + bn_result = bignum_init(); + + if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || + bn_result == NULL) + goto error; + + if (bignum_set_unsigned_bin(bn_base, base, base_len) < 0 || + bignum_set_unsigned_bin(bn_exp, power, power_len) < 0 || + bignum_set_unsigned_bin(bn_modulus, modulus, modulus_len) < 0) + goto error; + + if (bignum_exptmod(bn_base, bn_exp, bn_modulus, bn_result) < 0) + goto error; + + ret = bignum_get_unsigned_bin(bn_result, result, result_len); + +error: + bignum_deinit(bn_base); + bignum_deinit(bn_exp); + bignum_deinit(bn_modulus); + bignum_deinit(bn_result); + return ret; +} diff --git a/contrib/wpa/src/crypto/crypto_internal-rsa.c b/contrib/wpa/src/crypto/crypto_internal-rsa.c new file mode 100644 index 000000000000..205042cf3631 --- /dev/null +++ b/contrib/wpa/src/crypto/crypto_internal-rsa.c @@ -0,0 +1,115 @@ +/* + * Crypto wrapper for internal crypto implementation - RSA parts + * Copyright (c) 2006-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto.h" +#include "tls/rsa.h" +#include "tls/bignum.h" +#include "tls/pkcs1.h" +#include "tls/pkcs8.h" + +/* Dummy structures; these are just typecast to struct crypto_rsa_key */ +struct crypto_public_key; +struct crypto_private_key; + + +struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) +{ + return (struct crypto_public_key *) + crypto_rsa_import_public_key(key, len); +} + + +struct crypto_private_key * crypto_private_key_import(const u8 *key, + size_t len, + const char *passwd) +{ + struct crypto_private_key *res; + + /* First, check for possible PKCS #8 encoding */ + res = pkcs8_key_import(key, len); + if (res) + return res; + + if (passwd) { + /* Try to parse as encrypted PKCS #8 */ + res = pkcs8_enc_key_import(key, len, passwd); + if (res) + return res; + } + + /* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */ + wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private " + "key"); + return (struct crypto_private_key *) + crypto_rsa_import_private_key(key, len); +} + + +struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, + size_t len) +{ + /* No X.509 support in crypto_internal.c */ + return NULL; +} + + +int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, + const u8 *in, size_t inlen, + u8 *out, size_t *outlen) +{ + return pkcs1_encrypt(2, (struct crypto_rsa_key *) key, + 0, in, inlen, out, outlen); +} + + +int crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key, + const u8 *in, size_t inlen, + u8 *out, size_t *outlen) +{ + return pkcs1_v15_private_key_decrypt((struct crypto_rsa_key *) key, + in, inlen, out, outlen); +} + + +int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, + const u8 *in, size_t inlen, + u8 *out, size_t *outlen) +{ + return pkcs1_encrypt(1, (struct crypto_rsa_key *) key, + 1, in, inlen, out, outlen); +} + + +void crypto_public_key_free(struct crypto_public_key *key) +{ + crypto_rsa_free((struct crypto_rsa_key *) key); +} + + +void crypto_private_key_free(struct crypto_private_key *key) +{ + crypto_rsa_free((struct crypto_rsa_key *) key); +} + + +int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, + const u8 *crypt, size_t crypt_len, + u8 *plain, size_t *plain_len) +{ + return pkcs1_decrypt_public_key((struct crypto_rsa_key *) key, + crypt, crypt_len, plain, plain_len); +} diff --git a/contrib/wpa/src/crypto/crypto_internal.c b/contrib/wpa/src/crypto/crypto_internal.c index cddfb4de8ea9..8fdba6580275 100644 --- a/contrib/wpa/src/crypto/crypto_internal.c +++ b/contrib/wpa/src/crypto/crypto_internal.c @@ -1,6 +1,6 @@ /* - * WPA Supplicant / Crypto wrapper for internal crypto implementation - * Copyright (c) 2006-2007, Jouni Malinen + * Crypto wrapper for internal crypto implementation + * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,42 +16,8 @@ #include "common.h" #include "crypto.h" -#include "md5.h" -#include "sha1.h" -#include "rc4.h" -#include "aes.h" -#include "tls/rsa.h" -#include "tls/bignum.h" -#include "tls/asn1.h" - - -#ifdef CONFIG_CRYPTO_INTERNAL - -#ifdef CONFIG_TLS_INTERNAL - -/* from des.c */ -struct des3_key_s { - u32 ek[3][32]; - u32 dk[3][32]; -}; - -void des3_key_setup(const u8 *key, struct des3_key_s *dkey); -void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt); -void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain); - - -struct MD5Context { - u32 buf[4]; - u32 bits[2]; - u8 in[64]; -}; - -struct SHA1Context { - u32 state[5]; - u32 count[2]; - unsigned char buffer[64]; -}; - +#include "sha1_i.h" +#include "md5_i.h" struct crypto_hash { enum crypto_hash_alg alg; @@ -228,559 +194,6 @@ int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len) } -struct crypto_cipher { - enum crypto_cipher_alg alg; - union { - struct { - size_t used_bytes; - u8 key[16]; - size_t keylen; - } rc4; - struct { - u8 cbc[32]; - size_t block_size; - void *ctx_enc; - void *ctx_dec; - } aes; - struct { - struct des3_key_s key; - u8 cbc[8]; - } des3; - } u; -}; - - -struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, - const u8 *iv, const u8 *key, - size_t key_len) -{ - struct crypto_cipher *ctx; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) - return NULL; - - ctx->alg = alg; - - switch (alg) { - case CRYPTO_CIPHER_ALG_RC4: - if (key_len > sizeof(ctx->u.rc4.key)) { - os_free(ctx); - return NULL; - } - ctx->u.rc4.keylen = key_len; - os_memcpy(ctx->u.rc4.key, key, key_len); - break; - case CRYPTO_CIPHER_ALG_AES: - if (key_len > sizeof(ctx->u.aes.cbc)) { - os_free(ctx); - return NULL; - } - ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len); - if (ctx->u.aes.ctx_enc == NULL) { - os_free(ctx); - return NULL; - } - ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len); - if (ctx->u.aes.ctx_dec == NULL) { - aes_encrypt_deinit(ctx->u.aes.ctx_enc); - os_free(ctx); - return NULL; - } - ctx->u.aes.block_size = key_len; - os_memcpy(ctx->u.aes.cbc, iv, ctx->u.aes.block_size); - break; - case CRYPTO_CIPHER_ALG_3DES: - if (key_len != 24) { - os_free(ctx); - return NULL; - } - des3_key_setup(key, &ctx->u.des3.key); - os_memcpy(ctx->u.des3.cbc, iv, 8); - break; - default: - os_free(ctx); - return NULL; - } - - return ctx; -} - - -int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, - u8 *crypt, size_t len) -{ - size_t i, j, blocks; - - switch (ctx->alg) { - case CRYPTO_CIPHER_ALG_RC4: - if (plain != crypt) - os_memcpy(crypt, plain, len); - rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, - ctx->u.rc4.used_bytes, crypt, len); - ctx->u.rc4.used_bytes += len; - break; - case CRYPTO_CIPHER_ALG_AES: - if (len % ctx->u.aes.block_size) - return -1; - blocks = len / ctx->u.aes.block_size; - for (i = 0; i < blocks; i++) { - for (j = 0; j < ctx->u.aes.block_size; j++) - ctx->u.aes.cbc[j] ^= plain[j]; - aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc, - ctx->u.aes.cbc); - os_memcpy(crypt, ctx->u.aes.cbc, - ctx->u.aes.block_size); - plain += ctx->u.aes.block_size; - crypt += ctx->u.aes.block_size; - } - break; - case CRYPTO_CIPHER_ALG_3DES: - if (len % 8) - return -1; - blocks = len / 8; - for (i = 0; i < blocks; i++) { - for (j = 0; j < 8; j++) - ctx->u.des3.cbc[j] ^= plain[j]; - des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key, - ctx->u.des3.cbc); - os_memcpy(crypt, ctx->u.des3.cbc, 8); - plain += 8; - crypt += 8; - } - break; - default: - return -1; - } - - return 0; -} - - -int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, - u8 *plain, size_t len) -{ - size_t i, j, blocks; - u8 tmp[32]; - - switch (ctx->alg) { - case CRYPTO_CIPHER_ALG_RC4: - if (plain != crypt) - os_memcpy(plain, crypt, len); - rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen, - ctx->u.rc4.used_bytes, plain, len); - ctx->u.rc4.used_bytes += len; - break; - case CRYPTO_CIPHER_ALG_AES: - if (len % ctx->u.aes.block_size) - return -1; - blocks = len / ctx->u.aes.block_size; - for (i = 0; i < blocks; i++) { - os_memcpy(tmp, crypt, ctx->u.aes.block_size); - aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain); - for (j = 0; j < ctx->u.aes.block_size; j++) - plain[j] ^= ctx->u.aes.cbc[j]; - os_memcpy(ctx->u.aes.cbc, tmp, ctx->u.aes.block_size); - plain += ctx->u.aes.block_size; - crypt += ctx->u.aes.block_size; - } - break; - case CRYPTO_CIPHER_ALG_3DES: - if (len % 8) - return -1; - blocks = len / 8; - for (i = 0; i < blocks; i++) { - os_memcpy(tmp, crypt, 8); - des3_decrypt(crypt, &ctx->u.des3.key, plain); - for (j = 0; j < 8; j++) - plain[j] ^= ctx->u.des3.cbc[j]; - os_memcpy(ctx->u.des3.cbc, tmp, 8); - plain += 8; - crypt += 8; - } - break; - default: - return -1; - } - - return 0; -} - - -void crypto_cipher_deinit(struct crypto_cipher *ctx) -{ - switch (ctx->alg) { - case CRYPTO_CIPHER_ALG_AES: - aes_encrypt_deinit(ctx->u.aes.ctx_enc); - aes_decrypt_deinit(ctx->u.aes.ctx_dec); - break; - case CRYPTO_CIPHER_ALG_3DES: - break; - default: - break; - } - os_free(ctx); -} - - -/* Dummy structures; these are just typecast to struct crypto_rsa_key */ -struct crypto_public_key; -struct crypto_private_key; - - -struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) -{ - return (struct crypto_public_key *) - crypto_rsa_import_public_key(key, len); -} - - -#ifdef EAP_TLS_FUNCS -static struct crypto_private_key * -crypto_pkcs8_key_import(const u8 *buf, size_t len) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - struct bignum *zero; - struct asn1_oid oid; - char obuf[80]; - - /* PKCS #8, Chapter 6 */ - - /* PrivateKeyInfo ::= SEQUENCE */ - if (asn1_get_next(buf, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "PKCS #8: Does not start with PKCS #8 " - "header (SEQUENCE); assume PKCS #8 not used"); - return NULL; - } - pos = hdr.payload; - end = pos + hdr.length; - - /* version Version (Version ::= INTEGER) */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_INTEGER) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected INTEGER - found " - "class %d tag 0x%x; assume PKCS #8 not used", - hdr.class, hdr.tag); - return NULL; - } - - zero = bignum_init(); - if (zero == NULL) - return NULL; - - if (bignum_set_unsigned_bin(zero, hdr.payload, hdr.length) < 0) { - wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse INTEGER"); - bignum_deinit(zero); - return NULL; - } - pos = hdr.payload + hdr.length; - - if (bignum_cmp_d(zero, 0) != 0) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected zero INTEGER in the " - "beginning of private key; not found; assume " - "PKCS #8 not used"); - bignum_deinit(zero); - return NULL; - } - bignum_deinit(zero); - - /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier - * (PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier) */ - if (asn1_get_next(pos, len, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_SEQUENCE) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected SEQUENCE " - "(AlgorithmIdentifier) - found class %d tag 0x%x; " - "assume PKCS #8 not used", - hdr.class, hdr.tag); - return NULL; - } - - if (asn1_get_oid(hdr.payload, hdr.length, &oid, &pos)) { - wpa_printf(MSG_DEBUG, "PKCS #8: Failed to parse OID " - "(algorithm); assume PKCS #8 not used"); - return NULL; - } - - asn1_oid_to_str(&oid, obuf, sizeof(obuf)); - wpa_printf(MSG_DEBUG, "PKCS #8: algorithm=%s", obuf); - - if (oid.len != 7 || - oid.oid[0] != 1 /* iso */ || - oid.oid[1] != 2 /* member-body */ || - oid.oid[2] != 840 /* us */ || - oid.oid[3] != 113549 /* rsadsi */ || - oid.oid[4] != 1 /* pkcs */ || - oid.oid[5] != 1 /* pkcs-1 */ || - oid.oid[6] != 1 /* rsaEncryption */) { - wpa_printf(MSG_DEBUG, "PKCS #8: Unsupported private key " - "algorithm %s", obuf); - return NULL; - } - - pos = hdr.payload + hdr.length; - - /* privateKey PrivateKey (PrivateKey ::= OCTET STRING) */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, "PKCS #8: Expected OCTETSTRING " - "(privateKey) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return NULL; - } - wpa_printf(MSG_DEBUG, "PKCS #8: Try to parse RSAPrivateKey"); - - return (struct crypto_private_key *) - crypto_rsa_import_private_key(hdr.payload, hdr.length); -} -#endif /* EAP_TLS_FUNCS */ - - -struct crypto_private_key * crypto_private_key_import(const u8 *key, - size_t len) -{ - struct crypto_private_key *res; - - /* First, check for possible PKCS #8 encoding */ - res = crypto_pkcs8_key_import(key, len); - if (res) - return res; - - /* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */ - wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private " - "key"); - return (struct crypto_private_key *) - crypto_rsa_import_private_key(key, len); -} - - -struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, - size_t len) -{ - /* No X.509 support in crypto_internal.c */ - return NULL; -} - - -static int pkcs1_generate_encryption_block(u8 block_type, size_t modlen, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - size_t ps_len; - u8 *pos; - - /* - * PKCS #1 v1.5, 8.1: - * - * EB = 00 || BT || PS || 00 || D - * BT = 00 or 01 for private-key operation; 02 for public-key operation - * PS = k-3-||D||; at least eight octets - * (BT=0: PS=0x00, BT=1: PS=0xff, BT=2: PS=pseudorandom non-zero) - * k = length of modulus in octets (modlen) - */ - - if (modlen < 12 || modlen > *outlen || inlen > modlen - 11) { - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Invalid buffer " - "lengths (modlen=%lu outlen=%lu inlen=%lu)", - __func__, (unsigned long) modlen, - (unsigned long) *outlen, - (unsigned long) inlen); - return -1; - } - - pos = out; - *pos++ = 0x00; - *pos++ = block_type; /* BT */ - ps_len = modlen - inlen - 3; - switch (block_type) { - case 0: - os_memset(pos, 0x00, ps_len); - pos += ps_len; - break; - case 1: - os_memset(pos, 0xff, ps_len); - pos += ps_len; - break; - case 2: - if (os_get_random(pos, ps_len) < 0) { - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Failed to get " - "random data for PS", __func__); - return -1; - } - while (ps_len--) { - if (*pos == 0x00) - *pos = 0x01; - pos++; - } - break; - default: - wpa_printf(MSG_DEBUG, "PKCS #1: %s - Unsupported block type " - "%d", __func__, block_type); - return -1; - } - *pos++ = 0x00; - os_memcpy(pos, in, inlen); /* D */ - - return 0; -} - - -static int crypto_rsa_encrypt_pkcs1(int block_type, struct crypto_rsa_key *key, - int use_private, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - size_t modlen; - - modlen = crypto_rsa_get_modulus_len(key); - - if (pkcs1_generate_encryption_block(block_type, modlen, in, inlen, - out, outlen) < 0) - return -1; - - return crypto_rsa_exptmod(out, modlen, out, outlen, key, use_private); -} - - -int crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - return crypto_rsa_encrypt_pkcs1(2, (struct crypto_rsa_key *) key, - 0, in, inlen, out, outlen); -} - - -int crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - struct crypto_rsa_key *rkey = (struct crypto_rsa_key *) key; - int res; - u8 *pos, *end; - - res = crypto_rsa_exptmod(in, inlen, out, outlen, rkey, 1); - if (res) - return res; - - if (*outlen < 2 || out[0] != 0 || out[1] != 2) - return -1; - - /* Skip PS (pseudorandom non-zero octets) */ - pos = out + 2; - end = out + *outlen; - while (*pos && pos < end) - pos++; - if (pos == end) - return -1; - pos++; - - *outlen -= pos - out; - - /* Strip PKCS #1 header */ - os_memmove(out, pos, *outlen); - - return 0; -} - - -int crypto_private_key_sign_pkcs1(struct crypto_private_key *key, - const u8 *in, size_t inlen, - u8 *out, size_t *outlen) -{ - return crypto_rsa_encrypt_pkcs1(1, (struct crypto_rsa_key *) key, - 1, in, inlen, out, outlen); -} - - -void crypto_public_key_free(struct crypto_public_key *key) -{ - crypto_rsa_free((struct crypto_rsa_key *) key); -} - - -void crypto_private_key_free(struct crypto_private_key *key) -{ - crypto_rsa_free((struct crypto_rsa_key *) key); -} - - -int crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key, - const u8 *crypt, size_t crypt_len, - u8 *plain, size_t *plain_len) -{ - size_t len; - u8 *pos; - - len = *plain_len; - if (crypto_rsa_exptmod(crypt, crypt_len, plain, &len, - (struct crypto_rsa_key *) key, 0) < 0) - return -1; - - /* - * PKCS #1 v1.5, 8.1: - * - * EB = 00 || BT || PS || 00 || D - * BT = 00 or 01 - * PS = k-3-||D|| times (00 if BT=00) or (FF if BT=01) - * k = length of modulus in octets - */ - - if (len < 3 + 8 + 16 /* min hash len */ || - plain[0] != 0x00 || (plain[1] != 0x00 && plain[1] != 0x01)) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " - "structure"); - return -1; - } - - pos = plain + 3; - if (plain[1] == 0x00) { - /* BT = 00 */ - if (plain[2] != 0x00) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " - "PS (BT=00)"); - return -1; - } - while (pos + 1 < plain + len && *pos == 0x00 && pos[1] == 0x00) - pos++; - } else { - /* BT = 01 */ - if (plain[2] != 0xff) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " - "PS (BT=01)"); - return -1; - } - while (pos < plain + len && *pos == 0xff) - pos++; - } - - if (pos - plain - 2 < 8) { - /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ - wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " - "padding"); - return -1; - } - - if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { - wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " - "structure (2)"); - return -1; - } - pos++; - len -= pos - plain; - - /* Strip PKCS #1 header */ - os_memmove(plain, pos, len); - *plain_len = len; - - return 0; -} - - int crypto_global_init(void) { return 0; @@ -790,47 +203,3 @@ int crypto_global_init(void) void crypto_global_deinit(void) { } -#endif /* CONFIG_TLS_INTERNAL */ - - -#if defined(EAP_FAST) || defined(CONFIG_WPS) - -int crypto_mod_exp(const u8 *base, size_t base_len, - const u8 *power, size_t power_len, - const u8 *modulus, size_t modulus_len, - u8 *result, size_t *result_len) -{ - struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result; - int ret = -1; - - bn_base = bignum_init(); - bn_exp = bignum_init(); - bn_modulus = bignum_init(); - bn_result = bignum_init(); - - if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL || - bn_result == NULL) - goto error; - - if (bignum_set_unsigned_bin(bn_base, base, base_len) < 0 || - bignum_set_unsigned_bin(bn_exp, power, power_len) < 0 || - bignum_set_unsigned_bin(bn_modulus, modulus, modulus_len) < 0) - goto error; - - if (bignum_exptmod(bn_base, bn_exp, bn_modulus, bn_result) < 0) - goto error; - - ret = bignum_get_unsigned_bin(bn_result, result, result_len); - -error: - bignum_deinit(bn_base); - bignum_deinit(bn_exp); - bignum_deinit(bn_modulus); - bignum_deinit(bn_result); - return ret; -} - -#endif /* EAP_FAST || CONFIG_WPS */ - - -#endif /* CONFIG_CRYPTO_INTERNAL */ diff --git a/contrib/wpa/src/crypto/crypto_libtomcrypt.c b/contrib/wpa/src/crypto/crypto_libtomcrypt.c index e82097f10a00..52b67a713d69 100644 --- a/contrib/wpa/src/crypto/crypto_libtomcrypt.c +++ b/contrib/wpa/src/crypto/crypto_libtomcrypt.c @@ -16,7 +16,6 @@ #include #include "common.h" -#include "rc4.h" #include "crypto.h" #ifndef mp_init_multi @@ -29,7 +28,7 @@ #endif -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { hash_state md; size_t i; @@ -38,6 +37,7 @@ void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) for (i = 0; i < num_elem; i++) md4_process(&md, addr[i], len[i]); md4_done(&md, mac); + return 0; } @@ -62,8 +62,7 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) } -#ifdef EAP_TLS_FUNCS -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { hash_state md; size_t i; @@ -72,10 +71,11 @@ void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) for (i = 0; i < num_elem; i++) md5_process(&md, addr[i], len[i]); md5_done(&md, mac); + return 0; } -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { hash_state md; size_t i; @@ -84,6 +84,7 @@ void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) for (i = 0; i < num_elem; i++) sha1_process(&md, addr[i], len[i]); sha1_done(&md, mac); + return 0; } @@ -145,8 +146,6 @@ void aes_decrypt_deinit(void *ctx) } -#ifdef CONFIG_TLS_INTERNAL - struct crypto_hash { enum crypto_hash_alg alg; int error; @@ -451,7 +450,8 @@ struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len) struct crypto_private_key * crypto_private_key_import(const u8 *key, - size_t len) + size_t len, + const char *passwd) { int res; struct crypto_private_key *pk; @@ -697,7 +697,7 @@ void crypto_global_deinit(void) } -#ifdef EAP_FAST +#ifdef CONFIG_MODEXP int crypto_mod_exp(const u8 *base, size_t base_len, const u8 *power, size_t power_len, @@ -729,8 +729,4 @@ int crypto_mod_exp(const u8 *base, size_t base_len, return -1; } -#endif /* EAP_FAST */ - -#endif /* CONFIG_TLS_INTERNAL */ - -#endif /* EAP_TLS_FUNCS */ +#endif /* CONFIG_MODEXP */ diff --git a/contrib/wpa/src/crypto/crypto_none.c b/contrib/wpa/src/crypto/crypto_none.c index f18c2a8ded95..9f43775a6462 100644 --- a/contrib/wpa/src/crypto/crypto_none.c +++ b/contrib/wpa/src/crypto/crypto_none.c @@ -18,8 +18,9 @@ #include "crypto.h" -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { + return 0; } diff --git a/contrib/wpa/src/crypto/crypto_nss.c b/contrib/wpa/src/crypto/crypto_nss.c new file mode 100644 index 000000000000..fee4195ca4e3 --- /dev/null +++ b/contrib/wpa/src/crypto/crypto_nss.c @@ -0,0 +1,213 @@ +/* + * Crypto wrapper functions for NSS + * Copyright (c) 2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "crypto.h" + + +static int nss_hash(HASH_HashType type, unsigned int max_res_len, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + HASHContext *ctx; + size_t i; + unsigned int reslen; + + ctx = HASH_Create(type); + if (ctx == NULL) + return -1; + + HASH_Begin(ctx); + for (i = 0; i < num_elem; i++) + HASH_Update(ctx, addr[i], len[i]); + HASH_End(ctx, mac, &reslen, max_res_len); + HASH_Destroy(ctx); + + return 0; +} + + +void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) +{ + PK11Context *ctx = NULL; + PK11SlotInfo *slot; + SECItem *param = NULL; + PK11SymKey *symkey = NULL; + SECItem item; + int olen; + u8 pkey[8], next, tmp; + int i; + + /* Add parity bits to the key */ + next = 0; + for (i = 0; i < 7; i++) { + tmp = key[i]; + pkey[i] = (tmp >> i) | next | 1; + next = tmp << (7 - i); + } + pkey[i] = next | 1; + + slot = PK11_GetBestSlot(CKM_DES_ECB, NULL); + if (slot == NULL) { + wpa_printf(MSG_ERROR, "NSS: PK11_GetBestSlot failed"); + goto out; + } + + item.type = siBuffer; + item.data = pkey; + item.len = 8; + symkey = PK11_ImportSymKey(slot, CKM_DES_ECB, PK11_OriginDerive, + CKA_ENCRYPT, &item, NULL); + if (symkey == NULL) { + wpa_printf(MSG_ERROR, "NSS: PK11_ImportSymKey failed"); + goto out; + } + + param = PK11_GenerateNewParam(CKM_DES_ECB, symkey); + if (param == NULL) { + wpa_printf(MSG_ERROR, "NSS: PK11_GenerateNewParam failed"); + goto out; + } + + ctx = PK11_CreateContextBySymKey(CKM_DES_ECB, CKA_ENCRYPT, + symkey, param); + if (ctx == NULL) { + wpa_printf(MSG_ERROR, "NSS: PK11_CreateContextBySymKey(" + "CKM_DES_ECB) failed"); + goto out; + } + + if (PK11_CipherOp(ctx, cypher, &olen, 8, (void *) clear, 8) != + SECSuccess) { + wpa_printf(MSG_ERROR, "NSS: PK11_CipherOp failed"); + goto out; + } + +out: + if (ctx) + PK11_DestroyContext(ctx, PR_TRUE); + if (symkey) + PK11_FreeSymKey(symkey); + if (param) + SECITEM_FreeItem(param, PR_TRUE); +} + + +int rc4_skip(const u8 *key, size_t keylen, size_t skip, + u8 *data, size_t data_len) +{ + return -1; +} + + +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return nss_hash(HASH_AlgMD5, 16, num_elem, addr, len, mac); +} + + +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return nss_hash(HASH_AlgSHA1, 20, num_elem, addr, len, mac); +} + + +int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + return nss_hash(HASH_AlgSHA256, 32, num_elem, addr, len, mac); +} + + +void * aes_encrypt_init(const u8 *key, size_t len) +{ + return NULL; +} + + +void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) +{ +} + + +void aes_encrypt_deinit(void *ctx) +{ +} + + +void * aes_decrypt_init(const u8 *key, size_t len) +{ + return NULL; +} + + +void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) +{ +} + + +void aes_decrypt_deinit(void *ctx) +{ +} + + +int crypto_mod_exp(const u8 *base, size_t base_len, + const u8 *power, size_t power_len, + const u8 *modulus, size_t modulus_len, + u8 *result, size_t *result_len) +{ + return -1; +} + + +struct crypto_cipher { +}; + + +struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, + const u8 *iv, const u8 *key, + size_t key_len) +{ + return NULL; +} + + +int crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain, + u8 *crypt, size_t len) +{ + return -1; +} + + +int crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt, + u8 *plain, size_t len) +{ + return -1; +} + + +void crypto_cipher_deinit(struct crypto_cipher *ctx) +{ +} diff --git a/contrib/wpa/src/crypto/crypto_openssl.c b/contrib/wpa/src/crypto/crypto_openssl.c index a4c3415c4d18..08c98aff4ba1 100644 --- a/contrib/wpa/src/crypto/crypto_openssl.c +++ b/contrib/wpa/src/crypto/crypto_openssl.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / wrapper functions for libcrypto - * Copyright (c) 2004-2005, Jouni Malinen + * Copyright (c) 2004-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -14,15 +14,16 @@ #include "includes.h" #include -#include -#include -#include +#include #include #include #include #include +#include #include "common.h" +#include "wpabuf.h" +#include "dh_group5.h" #include "crypto.h" #if OPENSSL_VERSION_NUMBER < 0x00907000 @@ -33,16 +34,87 @@ des_ecb_encrypt((input), (output), *(ks), (enc)) #endif /* openssl < 0.9.7 */ - -void md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +static BIGNUM * get_group5_prime(void) { - MD4_CTX ctx; - size_t i; +#if OPENSSL_VERSION_NUMBER < 0x00908000 + static const unsigned char RFC3526_PRIME_1536[] = { + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC9,0x0F,0xDA,0xA2, + 0x21,0x68,0xC2,0x34,0xC4,0xC6,0x62,0x8B,0x80,0xDC,0x1C,0xD1, + 0x29,0x02,0x4E,0x08,0x8A,0x67,0xCC,0x74,0x02,0x0B,0xBE,0xA6, + 0x3B,0x13,0x9B,0x22,0x51,0x4A,0x08,0x79,0x8E,0x34,0x04,0xDD, + 0xEF,0x95,0x19,0xB3,0xCD,0x3A,0x43,0x1B,0x30,0x2B,0x0A,0x6D, + 0xF2,0x5F,0x14,0x37,0x4F,0xE1,0x35,0x6D,0x6D,0x51,0xC2,0x45, + 0xE4,0x85,0xB5,0x76,0x62,0x5E,0x7E,0xC6,0xF4,0x4C,0x42,0xE9, + 0xA6,0x37,0xED,0x6B,0x0B,0xFF,0x5C,0xB6,0xF4,0x06,0xB7,0xED, + 0xEE,0x38,0x6B,0xFB,0x5A,0x89,0x9F,0xA5,0xAE,0x9F,0x24,0x11, + 0x7C,0x4B,0x1F,0xE6,0x49,0x28,0x66,0x51,0xEC,0xE4,0x5B,0x3D, + 0xC2,0x00,0x7C,0xB8,0xA1,0x63,0xBF,0x05,0x98,0xDA,0x48,0x36, + 0x1C,0x55,0xD3,0x9A,0x69,0x16,0x3F,0xA8,0xFD,0x24,0xCF,0x5F, + 0x83,0x65,0x5D,0x23,0xDC,0xA3,0xAD,0x96,0x1C,0x62,0xF3,0x56, + 0x20,0x85,0x52,0xBB,0x9E,0xD5,0x29,0x07,0x70,0x96,0x96,0x6D, + 0x67,0x0C,0x35,0x4E,0x4A,0xBC,0x98,0x04,0xF1,0x74,0x6C,0x08, + 0xCA,0x23,0x73,0x27,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + }; + return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), NULL); +#else /* openssl < 0.9.8 */ + return get_rfc3526_prime_1536(NULL); +#endif /* openssl < 0.9.8 */ +} - MD4_Init(&ctx); - for (i = 0; i < num_elem; i++) - MD4_Update(&ctx, addr[i], len[i]); - MD4_Final(mac, &ctx); +#if OPENSSL_VERSION_NUMBER < 0x00908000 +#ifndef OPENSSL_NO_SHA256 +#ifndef OPENSSL_FIPS +#define NO_SHA256_WRAPPER +#endif +#endif + +#endif /* openssl < 0.9.8 */ + +#ifdef OPENSSL_NO_SHA256 +#define NO_SHA256_WRAPPER +#endif + +static int openssl_digest_vector(const EVP_MD *type, int non_fips, + size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + EVP_MD_CTX ctx; + size_t i; + unsigned int mac_len; + + EVP_MD_CTX_init(&ctx); +#ifdef CONFIG_FIPS +#ifdef OPENSSL_FIPS + if (non_fips) + EVP_MD_CTX_set_flags(&ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); +#endif /* OPENSSL_FIPS */ +#endif /* CONFIG_FIPS */ + if (!EVP_DigestInit_ex(&ctx, type, NULL)) { + wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestInit_ex failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + for (i = 0; i < num_elem; i++) { + if (!EVP_DigestUpdate(&ctx, addr[i], len[i])) { + wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestUpdate " + "failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + } + if (!EVP_DigestFinal(&ctx, mac, &mac_len)) { + wpa_printf(MSG_ERROR, "OpenSSL: EVP_DigestFinal failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + + return 0; +} + + +int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return openssl_digest_vector(EVP_md4(), 0, num_elem, addr, len, mac); } @@ -67,94 +139,72 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) } -void md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +int rc4_skip(const u8 *key, size_t keylen, size_t skip, + u8 *data, size_t data_len) { - MD5_CTX ctx; - size_t i; +#ifdef OPENSSL_NO_RC4 + return -1; +#else /* OPENSSL_NO_RC4 */ + EVP_CIPHER_CTX ctx; + int outl; + int res = -1; + unsigned char skip_buf[16]; - MD5_Init(&ctx); - for (i = 0; i < num_elem; i++) - MD5_Update(&ctx, addr[i], len[i]); - MD5_Final(mac, &ctx); -} + EVP_CIPHER_CTX_init(&ctx); + if (!EVP_CIPHER_CTX_set_padding(&ctx, 0) || + !EVP_CipherInit_ex(&ctx, EVP_rc4(), NULL, NULL, NULL, 1) || + !EVP_CIPHER_CTX_set_key_length(&ctx, keylen) || + !EVP_CipherInit_ex(&ctx, NULL, NULL, key, NULL, 1)) + goto out; - -void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) -{ - SHA_CTX ctx; - size_t i; - - SHA1_Init(&ctx); - for (i = 0; i < num_elem; i++) - SHA1_Update(&ctx, addr[i], len[i]); - SHA1_Final(mac, &ctx); -} - - -#ifndef CONFIG_NO_FIPS186_2_PRF -static void sha1_transform(u8 *state, const u8 data[64]) -{ - SHA_CTX context; - os_memset(&context, 0, sizeof(context)); - os_memcpy(&context.h0, state, 5 * 4); - SHA1_Transform(&context, data); - os_memcpy(state, &context.h0, 5 * 4); -} - - -int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) -{ - u8 xkey[64]; - u32 t[5], _t[5]; - int i, j, m, k; - u8 *xpos = x; - u32 carry; - - if (seed_len > sizeof(xkey)) - seed_len = sizeof(xkey); - - /* FIPS 186-2 + change notice 1 */ - - os_memcpy(xkey, seed, seed_len); - os_memset(xkey + seed_len, 0, 64 - seed_len); - t[0] = 0x67452301; - t[1] = 0xEFCDAB89; - t[2] = 0x98BADCFE; - t[3] = 0x10325476; - t[4] = 0xC3D2E1F0; - - m = xlen / 40; - for (j = 0; j < m; j++) { - /* XSEED_j = 0 */ - for (i = 0; i < 2; i++) { - /* XVAL = (XKEY + XSEED_j) mod 2^b */ - - /* w_i = G(t, XVAL) */ - os_memcpy(_t, t, 20); - sha1_transform((u8 *) _t, xkey); - _t[0] = host_to_be32(_t[0]); - _t[1] = host_to_be32(_t[1]); - _t[2] = host_to_be32(_t[2]); - _t[3] = host_to_be32(_t[3]); - _t[4] = host_to_be32(_t[4]); - os_memcpy(xpos, _t, 20); - - /* XKEY = (1 + XKEY + w_i) mod 2^b */ - carry = 1; - for (k = 19; k >= 0; k--) { - carry += xkey[k] + xpos[k]; - xkey[k] = carry & 0xff; - carry >>= 8; - } - - xpos += 20; - } - /* x_j = w_0|w_1 */ + while (skip >= sizeof(skip_buf)) { + size_t len = skip; + if (len > sizeof(skip_buf)) + len = sizeof(skip_buf); + if (!EVP_CipherUpdate(&ctx, skip_buf, &outl, skip_buf, len)) + goto out; + skip -= len; } - return 0; + if (EVP_CipherUpdate(&ctx, data, &outl, data, data_len)) + res = 0; + +out: + EVP_CIPHER_CTX_cleanup(&ctx); + return res; +#endif /* OPENSSL_NO_RC4 */ } -#endif /* CONFIG_NO_FIPS186_2_PRF */ + + +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return openssl_digest_vector(EVP_md5(), 0, num_elem, addr, len, mac); +} + + +#ifdef CONFIG_FIPS +int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + return openssl_digest_vector(EVP_md5(), 1, num_elem, addr, len, mac); +} +#endif /* CONFIG_FIPS */ + + +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + return openssl_digest_vector(EVP_sha1(), 0, num_elem, addr, len, mac); +} + + +#ifndef NO_SHA256_WRAPPER +int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + return openssl_digest_vector(EVP_sha256(), 0, num_elem, addr, len, + mac); +} +#endif /* NO_SHA256_WRAPPER */ void * aes_encrypt_init(const u8 *key, size_t len) @@ -310,7 +360,7 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, EVP_CIPHER_CTX_set_padding(&ctx->enc, 0); if (!EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, NULL, NULL) || !EVP_CIPHER_CTX_set_key_length(&ctx->enc, key_len) || - !EVP_EncryptInit_ex(&ctx->enc, cipher, NULL, key, iv)) { + !EVP_EncryptInit_ex(&ctx->enc, NULL, NULL, key, iv)) { EVP_CIPHER_CTX_cleanup(&ctx->enc); os_free(ctx); return NULL; @@ -320,7 +370,7 @@ struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, EVP_CIPHER_CTX_set_padding(&ctx->dec, 0); if (!EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, NULL, NULL) || !EVP_CIPHER_CTX_set_key_length(&ctx->dec, key_len) || - !EVP_DecryptInit_ex(&ctx->dec, cipher, NULL, key, iv)) { + !EVP_DecryptInit_ex(&ctx->dec, NULL, NULL, key, iv)) { EVP_CIPHER_CTX_cleanup(&ctx->enc); EVP_CIPHER_CTX_cleanup(&ctx->dec); os_free(ctx); @@ -358,3 +408,98 @@ void crypto_cipher_deinit(struct crypto_cipher *ctx) EVP_CIPHER_CTX_cleanup(&ctx->dec); os_free(ctx); } + + +void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) +{ + DH *dh; + struct wpabuf *pubkey = NULL, *privkey = NULL; + size_t publen, privlen; + + *priv = NULL; + *publ = NULL; + + dh = DH_new(); + if (dh == NULL) + return NULL; + + dh->g = BN_new(); + if (dh->g == NULL || BN_set_word(dh->g, 2) != 1) + goto err; + + dh->p = get_group5_prime(); + if (dh->p == NULL) + goto err; + + if (DH_generate_key(dh) != 1) + goto err; + + publen = BN_num_bytes(dh->pub_key); + pubkey = wpabuf_alloc(publen); + if (pubkey == NULL) + goto err; + privlen = BN_num_bytes(dh->priv_key); + privkey = wpabuf_alloc(privlen); + if (privkey == NULL) + goto err; + + BN_bn2bin(dh->pub_key, wpabuf_put(pubkey, publen)); + BN_bn2bin(dh->priv_key, wpabuf_put(privkey, privlen)); + + *priv = privkey; + *publ = pubkey; + return dh; + +err: + wpabuf_free(pubkey); + wpabuf_free(privkey); + DH_free(dh); + return NULL; +} + + +struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, + const struct wpabuf *own_private) +{ + BIGNUM *pub_key; + struct wpabuf *res = NULL; + size_t rlen; + DH *dh = ctx; + int keylen; + + if (ctx == NULL) + return NULL; + + pub_key = BN_bin2bn(wpabuf_head(peer_public), wpabuf_len(peer_public), + NULL); + if (pub_key == NULL) + return NULL; + + rlen = DH_size(dh); + res = wpabuf_alloc(rlen); + if (res == NULL) + goto err; + + keylen = DH_compute_key(wpabuf_mhead(res), pub_key, dh); + if (keylen < 0) + goto err; + wpabuf_put(res, keylen); + BN_free(pub_key); + + return res; + +err: + BN_free(pub_key); + wpabuf_free(res); + return NULL; +} + + +void dh5_free(void *ctx) +{ + DH *dh; + if (ctx == NULL) + return; + dh = ctx; + DH_free(dh); +} diff --git a/contrib/wpa/src/crypto/des.c b/contrib/wpa/src/crypto/des-internal.c similarity index 95% rename from contrib/wpa/src/crypto/des.c rename to contrib/wpa/src/crypto/des-internal.c index 103e592461a7..ccea9503216e 100644 --- a/contrib/wpa/src/crypto/des.c +++ b/contrib/wpa/src/crypto/des-internal.c @@ -2,7 +2,7 @@ * DES and 3DES-EDE ciphers * * Modifications to LibTomCrypt implementation: - * Copyright (c) 2006, Jouni Malinen + * Copyright (c) 2006-2009, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,9 +18,7 @@ #include "common.h" #include "crypto.h" - - -#ifdef INTERNAL_DES +#include "des_i.h" /* * This implementation is based on a DES implementation included in @@ -432,10 +430,34 @@ void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) } -struct des3_key_s { - u32 ek[3][32]; - u32 dk[3][32]; -}; +void des_key_setup(const u8 *key, u32 *ek, u32 *dk) +{ + deskey(key, 0, ek); + deskey(key, 1, dk); +} + + +void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt) +{ + u32 work[2]; + work[0] = WPA_GET_BE32(plain); + work[1] = WPA_GET_BE32(plain + 4); + desfunc(work, ek); + WPA_PUT_BE32(crypt, work[0]); + WPA_PUT_BE32(crypt + 4, work[1]); +} + + +void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain) +{ + u32 work[2]; + work[0] = WPA_GET_BE32(crypt); + work[1] = WPA_GET_BE32(crypt + 4); + desfunc(work, dk); + WPA_PUT_BE32(plain, work[0]); + WPA_PUT_BE32(plain + 4, work[1]); +} + void des3_key_setup(const u8 *key, struct des3_key_s *dkey) { @@ -475,5 +497,3 @@ void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain) WPA_PUT_BE32(plain, work[0]); WPA_PUT_BE32(plain + 4, work[1]); } - -#endif /* INTERNAL_DES */ diff --git a/contrib/wpa/src/crypto/des_i.h b/contrib/wpa/src/crypto/des_i.h new file mode 100644 index 000000000000..6f274144a0e6 --- /dev/null +++ b/contrib/wpa/src/crypto/des_i.h @@ -0,0 +1,31 @@ +/* + * DES and 3DES-EDE ciphers + * Copyright (c) 2006-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef DES_I_H +#define DES_I_H + +struct des3_key_s { + u32 ek[3][32]; + u32 dk[3][32]; +}; + +void des_key_setup(const u8 *key, u32 *ek, u32 *dk); +void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt); +void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain); + +void des3_key_setup(const u8 *key, struct des3_key_s *dkey); +void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt); +void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain); + +#endif /* DES_I_H */ diff --git a/contrib/wpa/src/crypto/dh_group5.c b/contrib/wpa/src/crypto/dh_group5.c new file mode 100644 index 000000000000..8c475bf94ae9 --- /dev/null +++ b/contrib/wpa/src/crypto/dh_group5.c @@ -0,0 +1,40 @@ +/* + * Diffie-Hellman group 5 operations + * Copyright (c) 2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "dh_groups.h" +#include "dh_group5.h" + + +void * dh5_init(struct wpabuf **priv, struct wpabuf **publ) +{ + *publ = dh_init(dh_groups_get(5), priv); + if (*publ == 0) + return NULL; + return (void *) 1; +} + + +struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, + const struct wpabuf *own_private) +{ + return dh_derive_shared(peer_public, own_private, dh_groups_get(5)); +} + + +void dh5_free(void *ctx) +{ +} diff --git a/contrib/wpa/src/crypto/dh_group5.h b/contrib/wpa/src/crypto/dh_group5.h new file mode 100644 index 000000000000..595f1114fe2b --- /dev/null +++ b/contrib/wpa/src/crypto/dh_group5.h @@ -0,0 +1,23 @@ +/* + * Diffie-Hellman group 5 operations + * Copyright (c) 2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#ifndef DH_GROUP5_H +#define DH_GROUP5_H + +void * dh5_init(struct wpabuf **priv, struct wpabuf **publ); +struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, + const struct wpabuf *own_private); +void dh5_free(void *ctx); + +#endif /* DH_GROUP5_H */ diff --git a/contrib/wpa/src/crypto/dh_groups.c b/contrib/wpa/src/crypto/dh_groups.c index 5f6008a6e2a2..7bd2fb7b4e21 100644 --- a/contrib/wpa/src/crypto/dh_groups.c +++ b/contrib/wpa/src/crypto/dh_groups.c @@ -619,11 +619,12 @@ struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public, if (crypto_mod_exp(wpabuf_head(peer_public), wpabuf_len(peer_public), wpabuf_head(own_private), wpabuf_len(own_private), dh->prime, dh->prime_len, - wpabuf_put(shared, shared_len), &shared_len) < 0) { + wpabuf_mhead(shared), &shared_len) < 0) { wpabuf_free(shared); wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed"); return NULL; } + wpabuf_put(shared, shared_len); wpa_hexdump_buf_key(MSG_DEBUG, "DH: shared key", shared); return shared; diff --git a/contrib/wpa/src/crypto/fips_prf_cryptoapi.c b/contrib/wpa/src/crypto/fips_prf_cryptoapi.c new file mode 100644 index 000000000000..17d3116e8b57 --- /dev/null +++ b/contrib/wpa/src/crypto/fips_prf_cryptoapi.c @@ -0,0 +1,25 @@ +/* + * FIPS 186-2 PRF for Microsoft CryptoAPI + * Copyright (c) 2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto.h" + + +int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) +{ + /* FIX: how to do this with CryptoAPI? */ + return -1; +} diff --git a/contrib/wpa/src/crypto/fips_prf_gnutls.c b/contrib/wpa/src/crypto/fips_prf_gnutls.c new file mode 100644 index 000000000000..f742e98589f2 --- /dev/null +++ b/contrib/wpa/src/crypto/fips_prf_gnutls.c @@ -0,0 +1,26 @@ +/* + * FIPS 186-2 PRF for libgcrypt + * Copyright (c) 2004-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" +#include + +#include "common.h" +#include "crypto.h" + + +int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) +{ + /* FIX: how to do this with libgcrypt? */ + return -1; +} diff --git a/contrib/wpa/src/crypto/fips_prf_internal.c b/contrib/wpa/src/crypto/fips_prf_internal.c new file mode 100644 index 000000000000..a85cb14d7424 --- /dev/null +++ b/contrib/wpa/src/crypto/fips_prf_internal.c @@ -0,0 +1,74 @@ +/* + * FIPS 186-2 PRF for internal crypto implementation + * Copyright (c) 2006-2007, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "sha1.h" +#include "sha1_i.h" +#include "crypto.h" + + +int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) +{ + u8 xkey[64]; + u32 t[5], _t[5]; + int i, j, m, k; + u8 *xpos = x; + u32 carry; + + if (seed_len > sizeof(xkey)) + seed_len = sizeof(xkey); + + /* FIPS 186-2 + change notice 1 */ + + os_memcpy(xkey, seed, seed_len); + os_memset(xkey + seed_len, 0, 64 - seed_len); + t[0] = 0x67452301; + t[1] = 0xEFCDAB89; + t[2] = 0x98BADCFE; + t[3] = 0x10325476; + t[4] = 0xC3D2E1F0; + + m = xlen / 40; + for (j = 0; j < m; j++) { + /* XSEED_j = 0 */ + for (i = 0; i < 2; i++) { + /* XVAL = (XKEY + XSEED_j) mod 2^b */ + + /* w_i = G(t, XVAL) */ + os_memcpy(_t, t, 20); + SHA1Transform(_t, xkey); + _t[0] = host_to_be32(_t[0]); + _t[1] = host_to_be32(_t[1]); + _t[2] = host_to_be32(_t[2]); + _t[3] = host_to_be32(_t[3]); + _t[4] = host_to_be32(_t[4]); + os_memcpy(xpos, _t, 20); + + /* XKEY = (1 + XKEY + w_i) mod 2^b */ + carry = 1; + for (k = 19; k >= 0; k--) { + carry += xkey[k] + xpos[k]; + xkey[k] = carry & 0xff; + carry >>= 8; + } + + xpos += SHA1_MAC_LEN; + } + /* x_j = w_0|w_1 */ + } + + return 0; +} diff --git a/contrib/wpa/src/crypto/fips_prf_nss.c b/contrib/wpa/src/crypto/fips_prf_nss.c new file mode 100644 index 000000000000..f941983c43c3 --- /dev/null +++ b/contrib/wpa/src/crypto/fips_prf_nss.c @@ -0,0 +1,25 @@ +/* + * FIPS 186-2 PRF for NSS + * Copyright (c) 2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" +#include + +#include "common.h" +#include "crypto.h" + + +int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen) +{ + return -1; +} diff --git a/contrib/wpa/src/crypto/fips_prf_openssl.c b/contrib/wpa/src/crypto/fips_prf_openssl.c new file mode 100644 index 000000000000..d0af98355f65 --- /dev/null +++ b/contrib/wpa/src/crypto/fips_prf_openssl.c @@ -0,0 +1,83 @@ +/* + * FIPS 186-2 PRF for libcrypto + * Copyright (c) 2004-2005, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" +#include