Tag Archives: WPA2

Unified Windows PE 3.1 builder script for WAIK, with wifi and EFI support

WinPE-with-WLAN

It’s useful to have wifi support with WPA/WPA2 in Windows PE for occasions where you may want to perform an OS install or a salvage on a machine without ethernet built-in: for instance a MacBook Air running Windows or a Sony Vaio P when you don’t have the breakout dongle to hand.

When I started researching wifi support I found that the people who had clearly got it working seemed to be unwilling to share their work. One tool for the job, Holger’s PE Network Manager did not work for me at all, and judging from the dates of the files it had been created for older versions of Windows PE than the current one. There are many third party Windows PE ‘builder’ apps out there that completely replace the official Microsoft WAIK tools. However these seem more aimed at hobbyists than pros and tend to over complicate by adding features that a deployment pro does not really need. Since they’re not-so-trustworthy compiled binaries I don’t feel comfortable using them for work purposes. I decided to carefully work out for myself which registry entries and which additional files are required. There are surprisingly few.

The following unified script will use the standard WAIK tools to create both x86 and x64 builds, or either one individually, and is designed to be run by double-clicking it. Notice the defined variables at the start, particularly the %SOURCE% folder. The script expects the following folders:

  • %SOURCE%\scripts\WinPE – OS build scripts, wifi config XML, optional CA certificates
  • %SOURCE%\drivers\WinPE-x86\CURRENT – drivers
  • %SOURCE%\drivers\WinPE-x64\CURRENT
  • %SOURCE%\tools\WinPE-x86 – optional tools such as GImageX, or apps from portableapps.com
  • %SOURCE%\tools\WinPE-x64
  • %SOURCE%\tools\WinPE-x86\WLAN – the WLAN system files see highlighted section in main script below
  • %SOURCE%\tools\WinPE-x64\WLAN
 

It also requires your WAIK installation to be updated to Windows PE 3.1 using the WAIK supplement for Windows 7 SP1.

I had originally wanted to connect WinPE clients to a WPA-Enterprise network but although Windows PE now supports 802.1x, it appears to work only for wired connections (see my comment on that post).

There is no GUI to manage the WLAN service, but I did find the necessary registry mod to enable the hooks already present in netsh.exe. You will need to use a working Windows 7 PC which is configured for the WLAN of your choice, then export its profile. You cannot connect to a wifi network in Windows PE without having done this. The PSK must not be encrypted since it will be imported onto a different machine (you need to run this with Administrator privileges or else the key parameter will be ignored):

netsh wlan show profiles
netsh wlan export profile name="YOURWLANSSIDHERE" folder="C:\temp" key=clear

Copy this XML file into the folder %SOURCE%\scripts\WinPE in the build tree. When Windows PE boots, you simply type wifi. This wifi.cmd script which is built by the main script will automatically import any XML profiles, list the available wifi networks, and display some example netsh syntax:

netsh wlan connect name=YOURWLANSSIDHERE ssid=YOURWLANSSIDHERE
 

The script

Save as %SOURCE%\scripts\Build_WinPE.cmd

:: Build_WinPE.cmd
::
:: This script will build x86 and x64 Windows PE, automatically
:: collecting drivers from the relevant folders within the
:: unattended installation, building WIM and ISO images, and
:: will also upload the WIM images to the deployment server(s).
::
:: DO NOT cancel this script in progress as you can end up with
:: orphaned locks on files inside mounted WIM images which
:: usually require a reboot of the server to clear.
::

@echo off
setlocal ENABLEDELAYEDEXPANSION

::variables
     set SOURCE=G:\unattended
     set PE_TEMP=C:\temp
     ::WinPE feature pack locale
     set PL=en-US
     ::commma separated list for WDS_SERVERS
     set WDS_SERVERS=FILESERVER1,FILESERVER2
::end variables

if not exist "C:\Program Files\Windows AIK\Tools\PETools\*.*" (
     echo This script requires the Windows Automatic Install Kit to be installed
     echo Download it from http://www.microsoft.com/download/en/details.aspx?id=5753
     echo.
     pause
     goto :eof
)
if "%1"=="relaunch" (
     call :BUILD_WINPE %2 %3 %4
     goto :eof
)
if "%1"=="unmount" (
     :: use this if you have a problem with the script and there are WIMs still mounted
     dism /Unmount-Wim /MountDir:"%PE_TEMP%\WinPE-x86\mount" /discard
     dism /Unmount-Wim /MountDir:"%PE_TEMP%\WinPE-x64\mount" /discard
     goto :eof
)
:prompt
cls
set /P SELECTION=Build WinPE for which CPU architecture (x64, x86, both)? [x64]: 
if "%SELECTION%"=="" set SELECTION=x64
if "%SELECTION%"=="x64" (
     start "Building Windows PE for x64 - NEVER CANCEL THIS SCRIPT IN PROGRESS" cmd /c "%0" relaunch x64 amd64
     goto :eof
)
if "%SELECTION%"=="x86" (
     start "Building Windows PE for x86 - NEVER CANCEL THIS SCRIPT IN PROGRESS" cmd /c "%0" relaunch x86 i386
     goto :eof
)
if "%SELECTION%"=="b" set SELECTION=both
if "%SELECTION%"=="both" (
     ::opening both instances of this script simultaneously seems to cause race conditions with dism.exe
     start /wait "Building Windows PE for x86 - NEVER CANCEL THIS SCRIPT IN PROGRESS" cmd /c "%0" relaunch x86 i386 nopause
     start "Building Windows PE for x64 - NEVER CANCEL THIS SCRIPT IN PROGRESS" cmd /c "%0" relaunch x64 amd64
     goto :eof
)
goto :prompt

:BUILD_WINPE
set PE_ARCH=%1
set PE_ARCH_LONG=%2
echo on
set PATH=%PATH%;C:\Program Files\Windows AIK\Tools\PETools\;C:\Program Files\Windows AIK\Tools\%PROCESSOR_ARCHITECTURE%
set PATH=%PATH%;C:\Program Files\Windows AIK\Tools\Servicing
rd /s /q %PE_TEMP%\WinPE-%PE_ARCH%

::Microsoft haven't used consistent naming in WAIK
if "%PE_ARCH%"=="x86" set WAIK_ARCH=%PE_ARCH%
if "%PE_ARCH%"=="x64" set WAIK_ARCH=%PE_ARCH_LONG%

call copype.cmd %WAIK_ARCH% %PE_TEMP%\WinPE-%PE_ARCH%
::package path
set PP=%ProgramFiles%\Windows AIK\Tools\PETools\%WAIK_ARCH%\WinPE_FPs
::image path
set IP=%PE_TEMP%\WinPE-%PE_ARCH%\mount
echo on
dism /Mount-Wim /WimFile:"%PE_TEMP%\WinPE-%PE_ARCH%\winpe.wim" /Index:1 /MountDir:"%IP%"
dism /image:"%IP%" /Add-Package /PackagePath:"%PP%\winpe-scripting.cab" /PackagePath:"%PP%\%PL%\winpe-scripting_%PL%.cab" /PackagePath:"%PP%\winpe-wmi.cab" /PackagePath:"%PP%\%PL%\winpe-wmi_%PL%.cab" /PackagePath:"%PP%\winpe-mdac.cab" /PackagePath:"%PP%\%PL%\winpe-mdac_%PL%.cab" /PackagePath:"%PP%\WinPE-HTA.cab" /PackagePath:"%PP%\%PL%\WinPE-HTA_%PL%.cab" /PackagePath:"%PP%\WINPE-DOT3SVC.CAB" /PackagePath:"%PP%\%PL%\WINPE-DOT3SVC_%PL%.CAB"
dism /image:"%IP%" /Add-Driver /driver:"%SOURCE%\drivers\WinPE-%PE_ARCH%\CURRENT" /Recurse
copy "%ProgramFiles%\Windows AIK\Tools\PETools\%WAIK_ARCH%\bootsect.exe" "%IP%\Windows"
copy /y "%SOURCE%\scripts\WinPE\*.*" "%IP%\Windows\System32"
copy "%SOURCE%\tools\WinPE-%PE_ARCH%\*.*" "%IP%\Windows\System32"
copy "%ProgramFiles%\Windows AIK\Tools\%WAIK_ARCH%\*.*" "%IP%\Windows\System32"


::add WLAN components
reg load HKLM\PE-BUILD-SYSTEM "%IP%\Windows\System32\config\SYSTEM"
reg load HKLM\PE-BUILD-SOFTWARE "%IP%\Windows\System32\config\SOFTWARE"
set KEY=HKLM\PE-BUILD-SYSTEM\ControlSet001\Enum\Root\LEGACY_WLANSVC
reg add %KEY% /v NextInstance /t REG_DWORD /d 1 /f
reg add %KEY%\0000 /v Service /t REG_SZ /d Wlansvc /f
reg add %KEY%\0000 /v Legacy /t REG_DWORD /d 1 /f
reg add %KEY%\0000 /v ConfigFlags /t REG_DWORD /d 0 /f
reg add %KEY%\0000 /v Class /t REG_SZ /d LegacyDriver /f
reg add %KEY%\0000 /v ClassGUID /t REG_SZ /d {8ECC055D-047F-11D1-A537-0000F8753ED1} /f
reg add %KEY%\0000 /v DeviceDesc /t REG_SZ /d "@%%SystemRoot%%\System32\wlansvc.dll,-257" /f
set KEY=HKLM\PE-BUILD-SYSTEM\ControlSet001\services\wlansvc
reg add %KEY% /v DisplayName /t REG_SZ /d "@%%SystemRoot%%\System32\wlansvc.dll,-257" /f
reg add %KEY% /v ErrorControl /t REG_DWORD /d 1 /f
reg add %KEY% /v Group /t REG_SZ /d TDI /f
reg add %KEY% /v ImagePath /t REG_EXPAND_SZ /d "%%SystemRoot%%\system32\svchost.exe -k LocalSystemNetworkRestricted" /f
reg add %KEY% /v Start /t REG_DWORD /d 2 /f
reg add %KEY% /v Type /t REG_DWORD /d 32 /f
reg add %KEY% /v Description /t REG_SZ /d "@%%SystemRoot%%\System32\wlansvc.dll,-258" /f
reg add %KEY% /v DependOnService /t REG_MULTI_SZ /d "nativewifip\0RpcSs\0Ndisuio\0Eaphost" /f
reg add %KEY% /v ObjectName /t REG_SZ /d LocalSystem /f
reg add %KEY% /v ServiceSidType /t REG_DWORD /d 1 /f
reg add %KEY% /v RequiredPrivileges /t REG_MULTI_SZ /d "SeChangeNotifyPrivilege\0SeImpersonatePrivilege\0SeAuditPrivilege\0SeTcbPrivilege\0SeDebugPrivilege" /f
reg add %KEY% /v FailureActions /t REG_BINARY /d 2c0100000000000000000000030000001400000001000000c0d4010001000000e09304000000000000000000 /f
reg add %KEY%\Enum /v 0 /t REG_SZ /d "Root\LEGACY_WLANSVC\0000" /f
reg add %KEY%\Enum /v Count /t REG_DWORD /d 1 /f
reg add %KEY%\Enum /v NextInstance /t REG_DWORD /d 1 /f
reg add %KEY%\Parameters /v ServiceDll /t REG_EXPAND_SZ /d "%%SystemRoot%%\System32\wlansvc.dll" /f
reg add %KEY%\Parameters /v ServiceDllUnloadOnStop /t REG_DWORD /d 1 /f
reg add %KEY%\Parameters /v ServiceMain /t REG_SZ /d WlanSvcMain /f
reg add HKLM\PE-BUILD-SOFTWARE\Microsoft\NetSh /v wlancfg /t REG_SZ /d wlancfg.dll /f
call :REG_MULTI_SZ-add "HKLM\PE-BUILD-SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost" LocalSystemNetworkRestricted wlansvc
xcopy /s "%SOURCE%\tools\WinPE-%PE_ARCH%\WLAN\*.*" "%IP%\Windows"
@echo off
:: These are the files that are required for WLAN (take them from Windows 7 machines of both CPU archs)
:: Put them in %SOURCE%\tools\WinPE-%PE_ARCH%\WLAN and create the same relative folder structure from C:\Windows onwards
:: so the file C:\Windows\inf\netnwifi.inf is copied to %SOURCE%\tools\WinPE-%PE_ARCH%\WLAN\inf\netnwifi.inf
::     C:\Windows\inf\netnwifi.inf
::     C:\Windows\inf\netvwififlt.inf
::     C:\Windows\inf\netvwifimp.inf
::     C:\Windows\l2schemas\wlan_policy_v1.xsd
::     C:\Windows\l2schemas\wlan_profile_v1.xsd
::     C:\Windows\l2schemas\wlanap_profile_v1.xsd
::     C:\Windows\schemas\availablenetwork\availablenetworkinfo.xsd
::     C:\Windows\system32\certutil.exe
::     C:\Windows\system32\wlanapi.dll
::     C:\Windows\system32\wlancfg.dll
::     C:\Windows\system32\wlanhlp.dll
::     C:\Windows\system32\wlanmsm.dll
::     C:\Windows\system32\wlansec.dll
::     C:\Windows\system32\wlansvc.dll
::     C:\Windows\system32\wlanui.dll
::     C:\Windows\system32\wlgpclnt.dll
::     C:\Windows\system32\drivers\nwifi.sys
::     C:\Windows\system32\drivers\vwififlt.sys
::     C:\Windows\system32\drivers\vwifimp.sys
::     C:\Windows\system32\en-US\certutil.exe.mui (or your locale's equivalent)
::     C:\Windows\system32\en-us\wlanapi.dll.mui
::     C:\Windows\system32\en-us\wlancfg.dll.mui
::     C:\Windows\system32\en-us\wlansvc.dll.mui
::     C:\Windows\system32\en-us\wlanui.dll.mui
::     C:\Windows\system32\en-us\wlgpclnt.dll.mui
echo on
reg unload HKLM\PE-BUILD-SYSTEM
reg unload HKLM\PE-BUILD-SOFTWARE
:: build wifi.cmd
(
     echo @echo off
     echo drvload X:\WINDOWS\Inf\netvwifimp.inf
     echo drvload X:\WINDOWS\Inf\netvwififlt.inf
     echo drvload X:\WINDOWS\Inf\netnwifi.inf
     echo netcfg -c s -i ms_nativewifip
     echo echo Importing detected CA certificate^(s^).
     echo for %%%%i in ^(*.cer^) do certutil -addstore root %%%%i
     echo echo.
     echo net start dot3svc
     echo net start wlansvc
     echo for %%%%i in ^("Wireless Network Connection*.xml"^) do netsh wlan add profile filename="%%%%i"
     echo netsh wlan show networks
     echo echo.
     echo echo use "netsh wlan" to manage the wifi connection like so:
     echo echo   netsh wlan connect name=YOURWLANHERE ssid=YOURWLANHERE
     echo echo   ipconfig /renew
     echo echo.
) > "%IP%\Windows\System32\wifi.cmd"

dism /Unmount-Wim /MountDir:"%IP%" /commit
imagex /export /boot /compress fast "%PE_TEMP%\WinPE-%PE_ARCH%\winpe.wim" 1 "%PE_TEMP%\WinPE-%PE_ARCH%\ISO\sources\boot.wim"
@echo off

::Mac OS BootCamp will look for autorun.inf in order to validate this disk as a Windows Installer CD
::adding this allows us to start unattended installs using WinPE
date /T > "%PE_TEMP%\WinPE-%PE_ARCH%\ISO\autorun.inf"

::x64 bootable ISO includes both BIOS & EFI boot loaders
if "%PE_ARCH%" == "x64" (
     set CD_CMD=oscdimg -m -o -u2 -udfver102 -bootdata:2#p0,e,b"%PE_TEMP%\WinPE-%PE_ARCH%\etfsboot.com"#pEF,e,b"%PE_TEMP%\WinPE-%PE_ARCH%\efisys.bin" "%PE_TEMP%\WinPE-%PE_ARCH%\ISO" "%PE_TEMP%\WinPE-%PE_ARCH%\winpe_%PE_ARCH_LONG%.iso"
) else ( 
     set CD_CMD=oscdimg -n -b"%PE_TEMP%\WinPE-%PE_ARCH%\etfsboot.com" "%PE_TEMP%\WinPE-%PE_ARCH%\ISO" "%PE_TEMP%\WinPE-%PE_ARCH%\winpe_%PE_ARCH_LONG%.iso"
)
echo on
%CD_CMD%
@echo off

::rename the WIM file to avoid having multiple image files on the WDS server with the same filename
ren "%PE_TEMP%\WinPE-%PE_ARCH%\ISO\sources\boot.wim" boot_%PE_ARCH_LONG%.wim
del "%PE_TEMP%\WinPE-%PE_ARCH%\winpe.wim"

for %%i in (%WDS_SERVERS%) do (
     echo.
     echo Adding/updating boot image on WDS server: %%i
     :: try to add the image first, if that fails then replace existing
     wdsutil /Verbose /Progress /Add-Image /ImageFile:"%PE_TEMP%\WinPE-%PE_ARCH%\ISO\sources\boot_%PE_ARCH_LONG%.wim" /Server:%%i /ImageType:Boot /Name:"Microsoft Windows PE (%PE_ARCH%)" || wdsutil /Verbose /Progress /Replace-Image /Image:"Microsoft Windows PE (%PE_ARCH%)" /ImageType:Boot /Architecture:%PE_ARCH% /ReplacementImage /Name:"Microsoft Windows PE (%PE_ARCH%)" /ImageFile:"%PE_TEMP%\WinPE-%PE_ARCH%\ISO\sources\boot_%PE_ARCH_LONG%.wim" /Server:%%i
     echo.
)
::rename the WIM back again so bootable USB devices can be created
ren "%PE_TEMP%\WinPE-%PE_ARCH%\ISO\sources\boot_%PE_ARCH_LONG%.wim" boot.wim
echo *******************************************************************
echo WDS boot image(s) updated
echo.
echo A bootable ISO of this image has been created at:
echo   %PE_TEMP%\WinPE-%PE_ARCH%\winpe_%PE_ARCH_LONG%.iso
echo.
echo To create a bootable USB key, use diskpart.exe to create a FAT32 partition
echo and mark it active, then copy the contents of this folder to its root:
echo   %PE_TEMP%\WinPE-%PE_ARCH%\ISO
echo.
echo FAT32 is required for EFI support.
echo.
if "%3"=="nopause" goto :eof
pause
goto :eof

:REG_MULTI_SZ-add
::subroutine to append a value to a multiple string value Registry entry
setlocal ENABLEEXTENSIONS
set KEY=%1
set VALUE=%2
for /f "tokens=2*" %%a in ('reg query %KEY% /v %VALUE% /t REG_MULTI_SZ ^| FIND "REG_MULTI_SZ"') do set DATA=%%b
set DATA=%DATA%\0%3
reg add %KEY% /v %VALUE% /t REG_MULTI_SZ /d %DATA% /f
 
 

Cisco wifi WPA2-Enterprise PEAP authentication with Active Directory

Business users increasingly expect full LAN access while working wirelessly around the workplace. On account of the perceived weakness of WPA cryptography many network administrators will tend to offer a separate guest network over wifi, but not the full corporate LAN. I was one of those people until I got this working six months ago. This solution supports Mac, PC clients, together with iOS devices (iPhone, iPad), and I would guess Linux too since it’s based on open standards.

There is a pretty comprehensive Cisco configuration example document on this subject, but there isn’t much information on the web apart from that. There are several drawbacks to that guide:-

  • it only outlines the GUI config of a centralised Cisco Wireless LAN Controller (not standalone Cisco wifi access points)
  • it deals with Windows Server 2003 IAS rather than its more current replacement: NPS, as introduced by Windows Server 2008.
  • it assumes that the client will be running Cisco wifi client software (presumably it pre-dates the introduction of Windows’ own Wireless Network control panel introduced with XP Service Pack 1).

The access points authenticate using PEAP which is EAP inside a TLS session, therefore a working PKI is required for creating the NPS server’s certificate. If you don’t already have it, install the Active Directory Certificate Services role to one of your Windows domain servers. As I mentioned in my LDAPS guide, that whole process is somewhat outside the scope of this blog post but do heed Microsoft’s warning:

Warning Before you install a certification authority (CA), you should be aware that you are creating or extending a public key infrastructure (PKI). Be sure to design a PKI that is appropriate for your organization. See PKI Design Brief Overview for additional information.

 

Windows PKI Problems

DCs should auto-enroll for their own certificates once that’s up and running. However I had huge difficulties with this. I installed the Active Directory Certificate Services role on a Windows Server 2008 R2 Domain Controller. I soon discovered that none of the other 2008 R2 DCs could auto-enroll for certificates (the Event Log reported RPC server unavailable in the failure event which was quite misleading). I could not manually enroll for certificates using the Certificates MMC snap-in either.

This held me up for a long time, and I was able to find several sources stating that the solution was to add the Domain Controllers to the group CERTSVC_DCOM_ACCESS, which didn’t work for me. In the end I found the solution in this Technet answer by Joson Zhou. Somebody in the distant past had apparently tampered the Active Directory group membership of Builtin\Users (CN=Users,CN=Builtin,DC=domain,DC=com) and had removed Interactive and Authenticated Users. It had been like this for years with no adverse impact. Since a DC has no local accounts it will use this AD group as its definition of which users have User privileges. I suppose that up until this time no service that would have been affected had been installed on a DC.
I called a business contact to verify against an external Active Directory and, sure enough, those missing groups should indeed have been members. The moment I corrected this I was able to enroll for a DC certificate. Sadly the Technet thread is locked so I wasn’t able to thank Joson, and unfortunately it seems you can’t send private messages. I don’t understand why anyone would be inclined to interfere with default Active Directory groups – searching only reveals this post. The guy asks if it’s best practice to remove Authenticated Users from that group and is pretty roundly slapped down. Perhaps people did this with NT 4.0, which my domain dates from.

I also had a recurring issue in the Event Logs where these DCs would fail to pull down the Certificate Revocation Lists from Microsoft and fail to refresh the Trusted Root certificates. Microsoft KB931125 was the only thing that fixed that. However, while troubleshooting this problem I ended up installing the Trusted Root CA update pack (from here I think), assuming I’d be able to uninstall it later if it didn’t improve things. Unfortunately it cannot be uninstalled, and it caused me another huge hold-up later on.

 

Configuring Network Policy Server

Once your Domain Controller has a certificate you can install the Network Policy Server role. Each access point (or only your WLC if you use LWAPP access points) will need to be on a static IP address, and have an entry in the RADIUS clients section of the NPS management MMC. When generating Pre-Shared Keys note that it seems Cisco devices do not tolerate keys containing a dollar sign, at least not in their WebUI.

NPS RADIUS client settings

The behaviour for Windows computers is that before logon the PC will authenticate and connect using its computer account (providing connectivity to the domain), then when the user logs in the wifi network is re-connected in that user context. You will therefore probably need an NPS Network Policy item for both cases (NPS -> Policies -> Network Policies) which will allow you to apply different settings to each (timeouts, etc.):

NPS policy for wireless computers
NPS policy for wireless users

In each of the policies be sure to select PEAP as the only EAP authentication type, with EAP-MSCHAP v2 as below, selecting your server’s certificate in the drop-down.
NPS server PEAP encryption settings

Make sure that your Connection Request Policies are not preventing connections (NPS -> Policies -> Connection Request Policies) – I think they are disabled by default.

 

Access Point Configuration

I won’t bother to describe the Cisco WLC configuration, since that is basically identical to Cisco’s own guide. However, one problem I had in testing was that I removed and re-added the RADIUS server settings on the WLC and I had forgotten that you need to specify your NPS server twice – once for Authentication, and separately once again for Accounting (assuming you’re using accounting), which is not the case in the Server Manager GUI on standalone access points:

Wireless LAN Controller RADIUS server settings

Not everyone has the budget for a WLC, or you might, like me, have combination of a WLC at one site but not at others. It’s not practical to use a single WLC for multiple sites since all LWAPP traffic is trunked back to the controller – you wouldn’t want that load on your site-to-site links. Here is a sample multiple SSID configuration for a standalone Cisco 1131AG Access Point (AIR-AP1131AG-E-K9). I’m not going to provide Cisco access point GUI screenshots, but if you want them the first part of the following guide covers that well:
http://blog.laurence.id.au/2010/03/running-peap-with-cisco-aeronet-1231g.html

My example access point config below relates to the following schematic. If you’re going to apply this config to a bare unit, substitute the IPs and VLANs to match your environment and remove the lines with keys or passwords.

Sample access point config schematic

!
! Last configuration change at 17:13:17 UTC Tue Feb 22 2011 by admin
! NVRAM config last updated at 17:14:03 UTC Tue Feb 22 2011 by admin
!
version 12.4
no service pad
service timestamps debug datetime msec
service timestamps log datetime msec
service password-encryption
!
hostname test-ap1
!
logging rate-limit console 9
enable secret 5 3242576EABCD3F3254$2
!
aaa new-model
!
!
aaa group server radius rad_eap
 server 172.16.2.50 auth-port 1645 acct-port 1646
!
aaa group server radius rad_mac
!
aaa group server radius rad_acct
 server 172.16.2.50 auth-port 1645 acct-port 1646
!
aaa group server radius rad_admin
!
aaa group server tacacs+ tac_admin
!
aaa group server radius rad_pmip
!
aaa group server radius dummy
!
aaa authentication login eap_methods group rad_eap
aaa authentication login mac_methods local
aaa authorization exec default local
aaa accounting network acct_methods start-stop group rad_acct
!
aaa session-id common
ip domain name domain.com
ip name-server 208.67.222.222
ip name-server 208.67.220.220
!
!
dot11 syslog
dot11 vlan-name Wifi-Corp-WLAN vlan 20
dot11 vlan-name Wifi-Guest-WLAN vlan 6
!
dot11 ssid Corp-WLAN
   vlan 20
   authentication open eap eap_methods
   authentication key-management wpa version 2
   accounting acct_methods
   mbssid guest-mode
!
dot11 ssid Guest-WLAN
   vlan 6
   authentication open
   authentication key-management wpa
   guest-mode
   mbssid guest-mode
   wpa-psk ascii 7 123475652142BCD122
!
power inline negotiation prestandard source
!
!
username admin privilege 15 secret 5 131412ABDEFEE42323
!
!
bridge irb
!
!
interface Dot11Radio0
 no ip address
 no ip route-cache
 !
 encryption mode ciphers tkip
 !
 encryption vlan 20 mode ciphers aes-ccm
 !
 encryption vlan 6 mode ciphers aes-ccm tkip
 !
 ssid Corp-WLAN
 !
 ssid Guest-WLAN
 !
 mbssid
 station-role root
!
interface Dot11Radio0.20
 encapsulation dot1Q 20 native
 no ip route-cache
 bridge-group 1
 bridge-group 1 subscriber-loop-control
 bridge-group 1 block-unknown-source
 no bridge-group 1 source-learning
 no bridge-group 1 unicast-flooding
 bridge-group 1 spanning-disabled
!
interface Dot11Radio0.6
 encapsulation dot1Q 6
 no ip route-cache
 bridge-group 6
 bridge-group 6 subscriber-loop-control
 bridge-group 6 block-unknown-source
 no bridge-group 6 source-learning
 no bridge-group 6 unicast-flooding
 bridge-group 6 spanning-disabled
!
interface Dot11Radio1
 no ip address
 no ip route-cache
 !
 encryption mode ciphers tkip
 !
 encryption vlan 20 mode ciphers aes-ccm
 !
 encryption vlan 6 mode ciphers aes-ccm tkip
 !
 ssid Corp-WLAN
 !
 ssid Guest-WLAN
 !
 no dfs band block
 mbssid
 channel dfs
 station-role root
!
interface Dot11Radio1.20
 encapsulation dot1Q 20 native
 no ip route-cache
 bridge-group 1
 bridge-group 1 subscriber-loop-control
 bridge-group 1 block-unknown-source
 no bridge-group 1 source-learning
 no bridge-group 1 unicast-flooding
 bridge-group 1 spanning-disabled
!
interface Dot11Radio1.6
 encapsulation dot1Q 6
 no ip route-cache
 bridge-group 6
 bridge-group 6 subscriber-loop-control
 bridge-group 6 block-unknown-source
 no bridge-group 6 source-learning
 no bridge-group 6 unicast-flooding
 bridge-group 6 spanning-disabled
!
interface FastEthernet0
 no ip address
 no ip route-cache
 duplex auto
 speed auto
!
interface FastEthernet0.20
 encapsulation dot1Q 20 native
 no ip route-cache
 bridge-group 1
 no bridge-group 1 source-learning
 bridge-group 1 spanning-disabled
!
interface FastEthernet0.6
 encapsulation dot1Q 6
 no ip route-cache
 bridge-group 6
 no bridge-group 6 source-learning
 bridge-group 6 spanning-disabled
!
interface BVI1
 ip address 172.16.2.238 255.255.255.0
 no ip route-cache
!
ip default-gateway 172.16.2.254
ip http server
no ip http secure-server
ip http help-path http://www.cisco.com/warp/public/779/smbiz/prodconfig/help/eag
ip radius source-interface BVI1
snmp-server community public RO
radius-server attribute 32 include-in-access-req format %h
radius-server host 172.16.2.50 auth-port 1645 acct-port 1646 key 7 14154A12D56B57231FDC235331292321631B212212034332
radius-server vsa send accounting
bridge 1 route ip
!
!
!
line con 0
line vty 0 4
!
sntp server 130.159.196.118
sntp server 195.66.148.150
sntp server 84.45.87.84
sntp broadcast client
end
 
 

The Final PKI Hurdle

Each time I tried to authenticate I got an Schannel Event Log error on the NPS server of “The message received was unexpected or badly formatted.” which exactly matched the symptoms described in Microsoft KB933430, although that was only intended for Windows Server 2003. This was confusing, but according to that article:

When asking for client authentication, this server sends a list of trusted certificate authorities to the client. The client uses this list to choose a client certificate that is trusted by the server. Currently, this server trusts so many certificate authorities that the list has grown too long. This list has thus been truncated. The administrator of this machine should review the certificate authorities trusted for client authentication and remove those that do not really need to be trusted.

I had been working on this issue sporadically and I had only got as far as getting the Enterprise CA online before going on holiday. Only later did I make the connection and remember the updated Trusted Root CA pack that I had loaded on in desperation. Consulting the Certificates MMC snap-in I discovered that the server had 304 trusted root CAs instead of nine! Windows Server 2008 and 2008 R2 do have a more generous storage allowance for sending CA certificates in the PEAP handshake but clearly 304 certificates was too much. Using another server as a reference machine I manually deleted all the superfluous CA certificates and I could finally authenticate via wifi!

 

Non-Domain Client Configuration

When connecting from non-domain machines or iOS devices, the issuing CA for the NPS server’s certificate will not be trusted. In iOS you will be prompted to accept it manually, but the situation is more complicated in Windows 7 (I haven’t tested older OS versions). In my tests the connection would be rejected upon providing the additional user credentials. You will need to export the CA server certificate by running the following command on your CA:

certutil -ca.cert c:\temp\domain-SERVERNAME-CA.cer
 

On the Windows 7 client use the Certificates MMC snap-in to import it into the user’s Trusted Root CA Certificate Store (run MMC.EXE, File -> Add/Remove Snap-in -> Certificates -> My User Account -> Trusted Root Certification Authorities -> Certificates -> right-click -> All Tasks -> Import).

Now if you try to connect you will get the following message:

The Credentials provided by the server could not be validated. We recommend that you terminate the connection and contact your administrator with the information provided in the details. You may still connect but doing so exposes you to a security risk by a possible rogue server.

 

I found that I couldn’t connect even if I ignored this warning. To get around this, you will need to create the wireless network manually using the following settings:

Manual connection settings for Windows 7 (part 1)

Make sure to manually select your CA which should be listed as below:

Manual connection settings for Windows 7 (part 2)

 

Windows AD Domain Client Configuration by Group Policy

Domain workstations can have their wireless networking configs entirely managed by Group Policy, including network preference order, auto connect options, whether to cache credentials and more. Domain members also implicitly trust the Domain CA. Be aware that Windows XP workstations are configured by a separate policy to Windows Vista and Windows 7. Both Group Policies are located at Computer Configuration -> Policies -> Windows Settings -> Security Settings -> Wireless Network (IEEE 802.11) Policies. It’s all pretty self-explanatory, and the security and encryption settings are broadly identical to those in the screenshots above, except that you do not need to specify the CA.

Remember to add your designated wifi users and computers to the AD groups you created for the NPS Network Policies!