espressif / ESP8266_NONOS_SDK

ESP8266 nonOS SDK
Other
929 stars 535 forks source link

WPA2 Enterprise PEAP outer identity wrong #5

Closed Jostikas closed 7 years ago

Jostikas commented 7 years ago

As discussed in http://bbs.espressif.com/viewtopic.php?t=2904#p10855 and http://bbs.espressif.com/viewtopic.php?t=2904#p11053 ,

The current implementation of WPA2-PEAP is incomplete: there is a hardcoded identity (anonymous@espressif.com) in libwpa2.a that is not replaced with the actual user identity.

For now there's a workaround by editing the libwpa2.a file directly, if the identity is shorter than the default one. anonymous@espressif.com should be replaced with the correct identity, zero-padding the end to 23 bytes.ing the end to 23 bytes.

Also, what do the functions wifi_station_set_enterprise_new_password and wifi_station_clear_enterprise_new_password do? At least for me, once I edited the libwpa2.a file, connecting worked with the functions without _new_, and the network uses MSCHAPv2.

log from before editing libwpa2.a:

[SDK version:2.1.0(116b762)]<\r><\n>
WPA2 ENTERPRISE VERSION: [v2.0] enable<\r><\n>
mode : sta(a0:20:a6:16:f2:08)<\r><\n>
add if0<\r><\n>
[mode: 0 -> 3]<\r><\n>
scandone<\r><\n>
state: 0 -> 2 (b0)<\r><\n>
state: 2 -> 3 (0)<\r><\n>
state: 3 -> 5 (10)<\r><\n>
add 0<\r><\n>
aid 34<\r><\n>
cnt <\r><\n>
pm open,type:2 0<\r><\n>
state: 5 -> 0 (2)<\r><\n>
rm 0<\r><\n>
pm close 7<\r><\n>
reconnect<\r><\n>
[disconnect from ssid eduroam, reason 204]<\r><\n>
scandone<\r><\n>
state: 0 -> 2 (b0)<\r><\n>
state: 2 -> 3 (0)<\r><\n>
state: 3 -> 5 (10)<\r><\n>
add 0<\r><\n>
aid 34<\r><\n>
cnt <\r><\n>
pm open,type:2 0<\r><\n>
state: 5 -> 0 (2)<\r><\n>
rm 0<\r><\n>
pm close 7<\r><\n>
reconnect<\r><\n>
[disconnect from ssid eduroam, reason 204]<\r><\n>
scandone<\r><\n>
state: 0 -> 2 (b0)<\r><\n>
state: 2 -> 3 (0)<\r><\n>
state: 3 -> 0 (c)<\r><\n>
[disconnect from ssid eduroam, reason 203]<\r><\n>
reconnect<\r><\n>
scandone<\r><\n>
state: 0 -> 2 (b0)<\r><\n>
state: 2 -> 3 (0)<\r><\n>
state: 3 -> 0 (c)<\r><\n>
[disconnect from ssid eduroam, reason 203]<\r><\n>
reconnect<\r><\n>
scandone<\r><\n>
state: 0 -> 2 (b0)<\r><\n>
state: 2 -> 3 (0)<\r><\n>
state: 3 -> 0 (c)<\r><\n>
[disconnect from ssid eduroam, reason 203]<\r><\n>

repeat ad infinitum with error code 203

Log after editing libwpa2.a:

[SDK version:2.0.0(5a875ba)]<\r><\n>
WPA2 ENTERPRISE VERSION: [v2.0] enable<\r><\n>
mode : sta(a0:20:a6:16:f2:08)<\r><\n>
add if0<\r><\n>
scandone<\r><\n>
state: 0 -> 2 (b0)<\r><\n>
state: 2 -> 3 (0)<\r><\n>
state: 3 -> 5 (10)<\r><\n>
add 0<\r><\n>
aid 36<\r><\n>
cnt <\r><\n>
EAP-PEAP: received 37 bytes encrypted data for Phase 2<\r><\n>
EAP-PEAP: received Phase 2: code=1 identifier=8 length=5<\r><\n>
EAP-PEAP: Phase 2 Request: type=1<\r><\n>
EAP-PEAP: received 69 bytes encrypted data for Phase 2<\r><\n>
EAP-PEAP: received Phase 2: code=1 identifier=9 length=34<\r><\n>
EAP-PEAP: Phase 2 Request: type=26<\r><\n>
EAP-PEAP: Selected Phase 2 EAP vendor 0 method 26<\r><\n>
EAP-MSCHAPV2: RX identifier 9 mschapv2_id 9<\r><\n>
EAP-MSCHAPV2: Generate Challenge Response<\r><\n>
EAP-PEAP: received 85 bytes encrypted data for Phase 2<\r><\n>
EAP-PEAP: received Phase 2: code=1 identifier=10 length=51<\r><\n>
EAP-PEAP: Phase 2 Request: type=26<\r><\n>
EAP-MSCHAPV2: RX identifier 10 mschapv2_id 9<\r><\n>
EAP-PEAP: received 37 bytes encrypted data for Phase 2<\r><\n>
EAP-PEAP: received Phase 2: code=1 identifier=11 length=11<\r><\n>
EAP-PEAP: Phase 2 Request: type=33<\r><\n>
3fff10c0 already freed<\r><\n>
<\r><\n>
connected with eduroam, channel 11<\r><\n>
dhcp client start...<\r><\n>
[connect to ssid eduroam, channel 11]<\r><\n>
ip:172.17.166.143,mask:255.255.240.0,gw:172.17.160.1<\r><\n>
[ip:172.17.166.143,mask:255.255.240.0,gw:172.17.160.1]<\r><\n>
pm open,type:2 0<\r><\n>
Michel-XU commented 7 years ago

The same problem like this and unfortunately, no eduroam network for me to test. Only by creating a freeradius server, but neither eap-peap nor also eap-tls can work. (Have tried the last NON-OS SDK) I think that it depends the setting of server, but if this api works in a very special environment, that means no compatibility to it.

Jostikas commented 7 years ago

Also, it seems that the authentication info is not persisted, leaving as the only option to have automatic logon to include the username and password in the code. Not good from a security point of view (I'm assuming espressif is using something stronger than ROT13 to store it in flash...)

gnif commented 7 years ago

In my case the radius server (freeradius) is configured not to care what the anonymous identity is and tests fine with eapol_test using anonymous@espressif.com via EAP-PEAP.

contents of test.conf

network={
    ssid="redacted"
    key_mgmt=WPA-EAP
    anonymous_identity="anonymous@espressif.com"
    identity="redacted"
    password="redacted"
    ca_cert="/home/redacted/crt/ca.pem"
    eapol_flags=3
}

Test session

# ./eapol_test -a192.168.50.200 -p1812 -sSEKRET -ctest.conf -r0

... snip ...
RADIUS message: code=1 (Access-Request) identifier=10 length=230
   Attribute 1 (User-Name) length=25
      Value: 'anonymous@espressif.com'
   Attribute 4 (NAS-IP-Address) length=6
      Value: 127.0.0.1
   Attribute 31 (Calling-Station-Id) length=19
      Value: '02-00-00-00-00-01'
   Attribute 12 (Framed-MTU) length=6
      Value: 1400
   Attribute 61 (NAS-Port-Type) length=6
      Value: 19
   Attribute 6 (Service-Type) length=6
      Value: 2
   Attribute 77 (Connect-Info) length=24
      Value: 'CONNECT 11Mbps 802.11b'
   Attribute 79 (EAP-Message) length=82
      Value: 020a005019001703010020fdd2803e744227d8bac56372962cadbdf0ece40e806569c166b7d6e155f7e1821703010020fdf16d6f8e6827557c37c0c3b8241a89003efc4d4cc83c1a232a888bac832265
   Attribute 24 (State) length=18
      Value: c4b23655cdb82fd037b686853f612fd0
   Attribute 80 (Message-Authenticator) length=18
      Value: 68e1a19c06cd94e190bd8f833d905314
... snip ...
EAPOL: Successfully fetched key (len=32)
PMK from EAPOL - hexdump(len=32): 10 a3 5f b2 52 74 5c df eb 06 77 cd 4f cb 14 15 a0 8b 9c c8 1e b9 d6 8c 42 dd 85 73 c8 a6 93 0a
No EAP-Key-Name received from server
WPA: Clear old PMK and PTK
EAP: deinitialize previously used EAP method (25, PEAP) at EAP deinit
ENGINE: engine deinit
MPPE keys OK: 1  mismatch: 0
SUCCESS

And here is the relevent section from the freeradius -X output

[eap] Request found, released from the list
[eap] EAP/peap
[eap] processing type peap
[peap] processing EAP-TLS
[peap] eaptls_verify returned 7 
[peap] Done initial handshake
[peap] eaptls_process returned 7 
[peap] EAPTLS_OK
[peap] Session established.  Decoding tunneled attributes.
[peap] Peap state phase2
[peap] EAP type mschapv2
[peap] Got tunneled request
    EAP-Message = 0xREDACTED
server  {
[peap] Setting User-Name to redacted

When my device attempts to connect it seems to be telling the server it is providing a client certificate, which it is not as I am using username/password authentication. If I generate a certificate and set it, I still get the same error on the radius server.

[eap] Request found, released from the list
[eap] EAP/peap
[eap] processing type peap
[peap] processing EAP-TLS
  TLS Length 7
[peap] Length Included
[peap] eaptls_verify returned 11 
[peap] <<< TLS 1.0 Alert [length 0002], fatal bad_certificate  
TLS Alert read:fatal:bad certificate
    TLS_accept: failed in unknown state
rlm_eap: SSL error error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate
SSL: SSL_read failed inside of TLS (-1), TLS session fails.

This occurs regardless of if I provide a client certificate or not. The relevent difference here seems to be [peap] Length Included, which indicates a flag is being set by the esp8226 to indicate there is a client certificate.

Here is my code

void ICACHE_FLASH_ATTR user_init(void)
{
    char ssid    [] = SSID;
    char username[] = EAP2_USER;
    char password[] = EAP2_PASS;
    struct station_config wifi_config;

    uart_div_modify(0, UART_CLK_FREQ/9600);
    os_delay_us(1000000);

    wifi_status_led_install(WIFI_LED_IO_NUM, WIFI_LED_IO_MUX, FUNC_GPIO0); 
    os_printf("[SDK version:%s]\n", system_get_sdk_version());

    // station mode: 
    if( !wifi_set_opmode(STATION_MODE) ) {
        os_printf("[failed setting station mode]\n");
    }

    // set station configuration, save to flash
    os_memset(&wifi_config, 0, sizeof(wifi_config));
    os_strcpy(wifi_config.ssid, ssid, os_strlen(ssid));
    wifi_station_set_config(&wifi_config);

    // WPA2-Enterprise
    wifi_station_set_wpa2_enterprise_auth(1);
    wifi_station_set_enterprise_username(username, sizeof(username));
    wifi_station_set_enterprise_password(password, sizeof(password));

    // CA Cert
    extern char  _binary_crt_ca_pem_start[];
    extern char  _binary_crt_ca_pem_end  [];
    unsigned int _binary_crt_ca_len = _binary_crt_ca_pem_end - _binary_crt_ca_pem_start;
    wifi_station_set_enterprise_ca_cert(_binary_crt_ca_pem_start, _binary_crt_ca_len);

    wifi_set_event_handler_cb(wifi_handle_event_cb);
}

I have also confirmed that _binary_crt_ca_pem_* is correct, I am embeddeding this in as a object file with the following Makefile rule

%.o: %.pem
    $(OBJCOPY) -I binary -O elf32-xtensa-le -B xtensa $< $@
gnif commented 7 years ago

Further investigation now shows that this is not a client certificate issue as I had initially thought, the error from freeradius is an error sent by the ESP8266, it is rejecting the server's certificate. Removing the call to wifi_station_set_enterprise_ca_cert does not bypass the issue either.

gnif commented 7 years ago

Seems that the device doesn't support SHA512 certificates! After dropping back go SHA256 the device can now authenticate properly using EAP-PEAP with MSCHAPv2

WPA2 ENTERPRISE VERSION: [v2.0] enable
mode : sta(a0:20:a6:18:6f:d4)
add if0
scandone
state: 0 -> 2 (b0)
state: 2 -> 3 (0)
state: 3 -> 5 (10)
add 0
aid 1
cnt 
EAP-PEAP: received 37 bytes encrypted data for Phase 2
EAP-PEAP: received Phase 2: code=1 identifier=151 length=5
EAP-PEAP: Phase 2 Request: type=1
EAP-PEAP: received 85 bytes encrypted data for Phase 2
EAP-PEAP: received Phase 2: code=1 identifier=152 length=49
EAP-PEAP: Phase 2 Request: type=26
EAP-PEAP: Selected Phase 2 EAP vendor 0 method 26
EAP-MSCHAPV2: RX identifier 152 mschapv2_id 152
EAP-MSCHAPV2: Generate Challenge Response
EAP-PEAP: received 85 bytes encrypted data for Phase 2
EAP-PEAP: received Phase 2: code=1 identifier=153 length=51
EAP-PEAP: Phase 2 Request: type=26
EAP-MSCHAPV2: RX identifier 153 mschapv2_id 152
EAP-PEAP: received 37 bytes encrypted data for Phase 2
EAP-PEAP: received Phase 2: code=1 identifier=154 length=11
EAP-PEAP: Phase 2 Request: type=33
3fff1628 already freed

connected with redacted, channel 7
dhcp client start...
[connect to ssid redacted, channel 7]
ip:192.168.50.156,mask:255.255.255.0,gw:192.168.50.1
[ip:192.168.50.156,mask:255.255.255.0,gw:192.168.50.1]
pm open,type:2 0
Michel-XU commented 7 years ago

@gnif Hi, i have tried the SHA256 certificates, but the same issue again. Could you write a tutorial to show that how you configure the freeradius not to care what the anonymous identity is and create the ca certificate?

In addation, maybe we need to configure authentication with Active Directory to solve the problem of the anonymous identity.

gnif commented 7 years ago

I am using Freeradius with a Samba AD server, but I believe this is not a requirement in making this work. The > SHA256 certificate issue does not resolve the outer/anonymous identity issue, it is just worth noting that the client will reject the auth on certs with > SHA256.

I am not well versed enough on Radius to comment on exactly why my setup is working, but at a guess I would say it is due to the fact that the authentication occurs on the inner-tunnel not the outer/default.

TimXia commented 7 years ago

@Jostikas @Michel-XU We will provide an API to set outer identity in the next version. wifi_station_set_enterprise_new_password sets the new password which is used to substitute the old password when eap-mschapv2 failure request message with error code ERROR_PASSWD_EXPIRED is received. @gnif ESP8266 does not support > SHA256 certificate. We will have a discussion about whether to support it or not.

Michel-XU commented 7 years ago

@TimXia That's a good news. Is it possible to know when the next version release? Thanks~

TimXia commented 7 years ago

@Michel-XU Do not need to wait for the next version. We will add the API as soon as possible.

FayeY commented 7 years ago

Hi, we have updated the SDK about the WPA2 issue, please have a try with it. Thanks for your interest in ESP8266!

gnif commented 7 years ago

@FayeY GREAT! Thanks. For SHA-512, simply a sensible error code would be enough to prevent a developer wasting a ton of time like I did trying to figure this one out.

For the record the two new API functions added are:

int wifi_station_set_enterprise_identity(u8 *identity, int len);
void wifi_station_clear_enterprise_identity(void);
kapyaar commented 6 years ago

@FayeY You are the only one I could find here who seem to be responding to WPA2-Enterprise related stuff. A bunch of us on the Arduino core side have been struggling to get ESP8266 to connect to enterprise networks. Could you please look into the various posts, info we have so may be you could guide us correctly?

https://github.com/esp8266/Arduino/issues/4698 https://github.com/esp8266/Arduino/issues/3442

As per @victorclaessen

It's probably never going to work until they fix this: https://bbs.espressif.com/viewtopic.php?f=66&t=5962&p=15165

Any help would be much appreciated

d-a-v commented 6 years ago

Hello,

I have the chance to have a full access (with logs) to the infamous eduroam network to which a bunch of esp8266 users would like to connect to. It's a wpa2-enterprise network.

It does not work here and I think for a simple reason: the ESP is using the MSCHAPV2 for the phase 2 authentication, but this network requires the PAP method. The required EAP method is TTLS which the ESP seems to honour according to the logs below.

10:48:37.588 -> EAP-TTLS: Start (server ver=0, own ver=0)
10:48:43.355 -> 0.0.0.0
10:48:43.388 -> EAP-TTLS: TLS done, proceed to Phase 2
10:48:43.388 -> EAP-TTLS: received 0 bytes encrypted data for Phase 2
10:48:43.389 -> EAP-TTLS: empty data in beginning of Phase 2 - use fake EAP-Request Identity
10:48:43.389 -> EAP-TTLS: Phase 2 MSCHAPV2 Request
10:48:43.389 -> 0.0.0.0
10:48:44.482 -> state: 5 -> 2 (2a0)
10:48:44.482 -> rm 0

FWIW,

Laconic logs of the radius server of my local network:

May 30 10:42:02 server-name radiusd[19784]: Login incorrect: [my-correct-login-name] (from client xxxx port 0 via TLS tunnel)
May 30 10:42:02 server-name radiusd[19784]: Login incorrect: [my-correct-login-name] (from client xxxx port 8201 cli 5C-CF-7F-C3-AD-51)  <- this is my ESP's mac address

So my questions are:

Thanks for your support

edit: relevant part of the source code (source)

  wifi_station_disconnect();
  struct station_config wifi_config;
  memset(&wifi_config, 0, sizeof(wifi_config));
  strcpy((char*)wifi_config.ssid, ssid);
  strcpy((char*)wifi_config.password, password);
  wifi_station_set_config(&wifi_config);
  memset(&wifi_config, 0, sizeof(wifi_config));
  strcpy((char*)wifi_config.ssid, ssid);
  wifi_station_set_config(&wifi_config);
  wifi_station_clear_cert_key();
  wifi_station_clear_enterprise_ca_cert();
  wifi_station_set_wpa2_enterprise_auth(1);
  wifi_station_set_enterprise_identity((uint8*)username, strlen(username));
  wifi_station_set_enterprise_username((uint8*)username, strlen(username));
  wifi_station_set_enterprise_password((uint8*)password, strlen(password));
  wifi_station_connect();

edit2: I just realized this is a closed issue. I will create a new one with this same message if it is not reopened within a few days.

victorclaessen commented 6 years ago

@d-a-v Thanks for this comment. Really insightful. Great to have someone with log access to eduroam.

I'm kind of confused now. In my institution, if I understand it correctly (from https://eva.eduroam.nl/help-en-support) we can use either TTLS/PAP or PEAP/MSCHAPv2. And my ESP8266 won't connect so I figure it must be trying another combination. When I set up my own radius server to emulate eduroam (in order to be able to see some logs), I seemed to have the problem that the ESP8266 did not select MSCHAPv2 (as described in my bug report on their bbs [see link above]), but your experience suggests otherwise.

d-a-v commented 6 years ago

Maybe the esp knows only TTLS/MSCHAPV2 ? Was your own setup using TTLS or PEAP ? Would you be able to make a TTLS/MSCHAPv2 setup and try with it ?

edit: greping libwpa2.a, TTLS, PEAP for phase1, and MSCHAPV2 phase2 seem to be known, not PAP.

victorclaessen commented 6 years ago

Excellent question. Honestly, I am not sure. It was august last year. I'll have to think about how I did it in the first place and see if I can replicate it.

kapyaar commented 6 years ago

@d-a-v Thanks for responding. I have access to an eduroam network but not to its logs. Hence I got my own enterprise router TPLINK EAP120. I used an external radius server, and was able to see the logs. Hope you saw my posts, and findings that I posted on https://github.com/esp8266/Arduino/issues/4698.

You said

Maybe the esp knows only TTLS/MSCHAPV2 ? Was your own setup using TTLS or PEAP ? Would you be able to make a TTLS/MSCHAPv2 setup and try with it ?

As far as the test codes I tried, I do not see an option to set any of this. Do you mean to set this in the code? or is this something to be set on the router or radius side?

I can do more tests if you can provide some info as to where to make those above changes you suggested. I still have all the stuff with me.

d-a-v commented 6 years ago

@kapyaar I mean in the code. There seems to be currently no option in the API to select phase1 or phase2 methods.

I don't know if they can be automatically selected by protocol, and if so, if the esp does this. And there is not any reference to the phase2 'PAP' method in the firmware (libwpa2.a) which is sometimes used, at least by some eduroam network.

I think a new issue should be opened with only the minimum relevant details about all this.

kapyaar commented 6 years ago

@d-a-v ok I see. Yeah, I could not find any reference to setting/ selecting methods on the ESP side.

Further, I am not well versed to the core terminology of WPA2- Enterprise, I am just playing around on the top layer (user level). It looks like like this issue was raised on ESP forums before as @victorclaessen pointed out. Though an Espressif member responded promising a fix on an upcoming update, that date has passed, an update was released but yet no signs of addressing this.

So my questions are

  1. My tests are based on SDK:2.2.1(cfd48f3)/Core:2.4.1/lwIP:2.0.3(STABLE-2_0_3_RELEASE/glue:arduino-2.4.1)

Do you know if there anything newer that I am not aware of that addresses this?

  1. I can post a new issue, but do you think I should ? or someone with more indepth knowledge of the issue should? I can do user tests no issues there.
kapyaar commented 6 years ago

@d-a-v Would you be able to open a new issue with just the relevant issues only on this matter as you had suggested?

d-a-v commented 6 years ago

@kapyaar #133