eap_ttls.c

Go to the documentation of this file.
00001 
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 
00020 #include "common.h"
00021 #include "eap_i.h"
00022 #include "eap_tls_common.h"
00023 #include "wpa_supplicant.h"
00024 #include "config_ssid.h"
00025 #include "ms_funcs.h"
00026 #include "crypto.h"
00027 #include "tls.h"
00028 #include "eap_ttls.h"
00029 
00030 
00031 static void eap_ttls_deinit(struct eap_sm *sm, void *priv);
00032 
00033 
00034 struct eap_ttls_data {
00035         struct eap_ssl_data ssl;
00036 
00037         const struct eap_method *phase2_method;
00038         void *phase2_priv;
00039         int phase2_success;
00040         int phase2_start;
00041 
00042         enum {
00043                 EAP_TTLS_PHASE2_EAP,
00044                 EAP_TTLS_PHASE2_MSCHAPV2,
00045                 EAP_TTLS_PHASE2_MSCHAP,
00046                 EAP_TTLS_PHASE2_PAP,
00047                 EAP_TTLS_PHASE2_CHAP
00048         } phase2_type;
00049         u8 phase2_eap_type;
00050         u8 *phase2_eap_types;
00051         size_t num_phase2_eap_types;
00052 
00053         u8 auth_response[20];
00054         int auth_response_valid;
00055         u8 ident;
00056         int resuming; /* starting a resumed session */
00057         int reauth; /* reauthentication */
00058         u8 *key_data;
00059 
00060         u8 *pending_phase2_req;
00061         size_t pending_phase2_req_len;
00062 };
00063 
00064 
00065 static void * eap_ttls_init(struct eap_sm *sm)
00066 {
00067         struct eap_ttls_data *data;
00068         struct wpa_ssid *config = eap_get_config(sm);
00069         char *selected;
00070 
00071         data = malloc(sizeof(*data));
00072         if (data == NULL)
00073                 return NULL;
00074         memset(data, 0, sizeof(*data));
00075         selected = "EAP";
00076         data->phase2_type = EAP_TTLS_PHASE2_EAP;
00077         if (config && config->phase2) {
00078                 if (strstr(config->phase2, "autheap=")) {
00079                         selected = "EAP";
00080                         data->phase2_type = EAP_TTLS_PHASE2_EAP;
00081                 } else if (strstr(config->phase2, "auth=MSCHAPV2")) {
00082                         selected = "MSCHAPV2";
00083                         data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;
00084                 } else if (strstr(config->phase2, "auth=MSCHAP")) {
00085                         selected = "MSCHAP";
00086                         data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;
00087                 } else if (strstr(config->phase2, "auth=PAP")) {
00088                         selected = "PAP";
00089                         data->phase2_type = EAP_TTLS_PHASE2_PAP;
00090                 } else if (strstr(config->phase2, "auth=CHAP")) {
00091                         selected = "CHAP";
00092                         data->phase2_type = EAP_TTLS_PHASE2_CHAP;
00093                 }
00094         }
00095         wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected);
00096 
00097         if (data->phase2_type == EAP_TTLS_PHASE2_EAP) {
00098                 if (config && config->phase2) {
00099                         char *start, *pos, *buf;
00100                         u8 method, *methods = NULL, *_methods;
00101                         size_t num_methods = 0;
00102                         start = buf = strdup(config->phase2);
00103                         if (buf == NULL) {
00104                                 eap_ttls_deinit(sm, data);
00105                                 return NULL;
00106                         }
00107                         while (start && *start != '\0') {
00108                                 pos = strstr(start, "autheap=");
00109                                 if (pos == NULL)
00110                                         break;
00111                                 if (start != pos && *(pos - 1) != ' ') {
00112                                         start = pos + 8;
00113                                         continue;
00114                                 }
00115 
00116                                 start = pos + 8;
00117                                 pos = strchr(start, ' ');
00118                                 if (pos)
00119                                         *pos++ = '\0';
00120                                 method = eap_get_phase2_type(start);
00121                                 if (method == EAP_TYPE_NONE) {
00122                                         wpa_printf(MSG_ERROR, "EAP-TTLS: "
00123                                                    "Unsupported Phase2 EAP "
00124                                                    "method '%s'", start);
00125                                 } else {
00126                                         num_methods++;
00127                                         _methods = realloc(methods,
00128                                                            num_methods);
00129                                         if (_methods == NULL) {
00130                                                 free(methods);
00131                                                 free(buf);
00132                                                 eap_ttls_deinit(sm, data);
00133                                                 return NULL;
00134                                         }
00135                                         methods = _methods;
00136                                         methods[num_methods - 1] = method;
00137                                 }
00138 
00139                                 start = pos;
00140                         }
00141                         free(buf);
00142                         data->phase2_eap_types = methods;
00143                         data->num_phase2_eap_types = num_methods;
00144                 }
00145                 if (data->phase2_eap_types == NULL) {
00146                         data->phase2_eap_types = eap_get_phase2_types(
00147                                 config, &data->num_phase2_eap_types);
00148                 }
00149                 if (data->phase2_eap_types == NULL) {
00150                         wpa_printf(MSG_ERROR, "EAP-TTLS: No Phase2 EAP method "
00151                                    "available");
00152                         eap_ttls_deinit(sm, data);
00153                         return NULL;
00154                 }
00155                 wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase2 EAP types",
00156                             data->phase2_eap_types,
00157                             data->num_phase2_eap_types);
00158                 data->phase2_eap_type = EAP_TYPE_NONE;
00159         }
00160 
00161 
00162         if (eap_tls_ssl_init(sm, &data->ssl, config)) {
00163                 wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
00164                 eap_ttls_deinit(sm, data);
00165                 return NULL;
00166         }
00167 
00168         return data;
00169 }
00170 
00171 
00172 static void eap_ttls_deinit(struct eap_sm *sm, void *priv)
00173 {
00174         struct eap_ttls_data *data = priv;
00175         if (data == NULL)
00176                 return;
00177         if (data->phase2_priv && data->phase2_method)
00178                 data->phase2_method->deinit(sm, data->phase2_priv);
00179         free(data->phase2_eap_types);
00180         eap_tls_ssl_deinit(sm, &data->ssl);
00181         free(data->key_data);
00182         free(data->pending_phase2_req);
00183         free(data);
00184 }
00185 
00186 
00187 static int eap_ttls_encrypt(struct eap_sm *sm, struct eap_ttls_data *data,
00188                             int id, const u8 *plain, size_t plain_len,
00189                             u8 **out_data, size_t *out_len)
00190 {
00191         int res;
00192         u8 *pos;
00193         struct eap_hdr *resp;
00194 
00195         /* TODO: add support for fragmentation, if needed. This will need to
00196          * add TLS Message Length field, if the frame is fragmented. */
00197         resp = malloc(sizeof(struct eap_hdr) + 2 + data->ssl.tls_out_limit);
00198         if (resp == NULL)
00199                 return -1;
00200 
00201         resp->code = EAP_CODE_RESPONSE;
00202         resp->identifier = id;
00203 
00204         pos = (u8 *) (resp + 1);
00205         *pos++ = EAP_TYPE_TTLS;
00206         *pos++ = 0;
00207 
00208         res = tls_connection_encrypt(sm->ssl_ctx, data->ssl.conn,
00209                                      plain, plain_len,
00210                                      pos, data->ssl.tls_out_limit);
00211         if (res < 0) {
00212                 wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt Phase 2 "
00213                            "data");
00214                 free(resp);
00215                 return -1;
00216         }
00217 
00218         *out_len = sizeof(struct eap_hdr) + 2 + res;
00219         resp->length = host_to_be16(*out_len);
00220         *out_data = (u8 *) resp;
00221         return 0;
00222 }
00223 
00224 
00225 static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id,
00226                              int mandatory, size_t len)
00227 {
00228         struct ttls_avp_vendor *avp;
00229         u8 flags;
00230         size_t hdrlen;
00231 
00232         avp = (struct ttls_avp_vendor *) avphdr;
00233         flags = mandatory ? AVP_FLAGS_MANDATORY : 0;
00234         if (vendor_id) {
00235                 flags |= AVP_FLAGS_VENDOR;
00236                 hdrlen = sizeof(*avp);
00237                 avp->vendor_id = host_to_be32(vendor_id);
00238         } else {
00239                 hdrlen = sizeof(struct ttls_avp);
00240         }
00241 
00242         avp->avp_code = host_to_be32(avp_code);
00243         avp->avp_length = host_to_be32((flags << 24) | (hdrlen + len));
00244 
00245         return avphdr + hdrlen;
00246 }
00247 
00248 
00249 static u8 * eap_ttls_avp_add(u8 *start, u8 *avphdr, u32 avp_code,
00250                              u32 vendor_id, int mandatory,
00251                              u8 *data, size_t len)
00252 {
00253         u8 *pos;
00254         pos = eap_ttls_avp_hdr(avphdr, avp_code, vendor_id, mandatory, len);
00255         memcpy(pos, data, len);
00256         pos += len;
00257         AVP_PAD(start, pos);
00258         return pos;
00259 }
00260 
00261 
00262 static int eap_ttls_avp_encapsulate(u8 **resp, size_t *resp_len, u32 avp_code,
00263                                     int mandatory)
00264 {
00265         u8 *avp, *pos;
00266 
00267         avp = malloc(sizeof(struct ttls_avp) + *resp_len + 4);
00268         if (avp == NULL) {
00269                 free(*resp);
00270                 *resp = NULL;
00271                 *resp_len = 0;
00272                 return -1;
00273         }
00274 
00275         pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, *resp_len);
00276         memcpy(pos, *resp, *resp_len);
00277         pos += *resp_len;
00278         AVP_PAD(avp, pos);
00279         free(*resp);
00280         *resp = avp;
00281         *resp_len = pos - avp;
00282         return 0;
00283 }
00284 
00285 
00286 static int eap_ttls_phase2_nak(struct eap_sm *sm,
00287                                struct eap_ttls_data *data,
00288                                struct eap_hdr *hdr,
00289                                u8 **resp, size_t *resp_len)
00290 {
00291         struct eap_hdr *resp_hdr;
00292         u8 *pos = (u8 *) (hdr + 1);
00293 
00294         wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 Request: Nak type=%d", *pos);
00295         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Allowed Phase2 EAP types",
00296                     data->phase2_eap_types, data->num_phase2_eap_types);
00297         *resp_len = sizeof(struct eap_hdr) + 1 + data->num_phase2_eap_types;
00298         *resp = malloc(*resp_len);
00299         if (*resp == NULL)
00300                 return -1;
00301 
00302         resp_hdr = (struct eap_hdr *) (*resp);
00303         resp_hdr->code = EAP_CODE_RESPONSE;
00304         resp_hdr->identifier = hdr->identifier;
00305         resp_hdr->length = host_to_be16(*resp_len);
00306         pos = (u8 *) (resp_hdr + 1);
00307         *pos++ = EAP_TYPE_NAK;
00308         memcpy(pos, data->phase2_eap_types, data->num_phase2_eap_types);
00309 
00310         return 0;
00311 }
00312 
00313 
00314 static int eap_ttls_phase2_request_eap(struct eap_sm *sm,
00315                                        struct eap_ttls_data *data,
00316                                        struct eap_method_ret *ret,
00317                                        const struct eap_hdr *req,
00318                                        struct eap_hdr *hdr,
00319                                        u8 **resp, size_t *resp_len)
00320 {
00321         size_t len = be_to_host16(hdr->length);
00322         u8 *pos;
00323         struct eap_method_ret iret;
00324         struct wpa_ssid *config = eap_get_config(sm);
00325 
00326         if (len <= sizeof(struct eap_hdr)) {
00327                 wpa_printf(MSG_INFO, "EAP-TTLS: too short "
00328                            "Phase 2 request (len=%lu)", (unsigned long) len);
00329                 return -1;
00330         }
00331         pos = (u8 *) (hdr + 1);
00332         wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d", *pos);
00333         switch (*pos) {
00334         case EAP_TYPE_IDENTITY:
00335                 *resp = eap_sm_buildIdentity(sm, req->identifier, resp_len, 1);
00336                 break;
00337         default:
00338                 if (data->phase2_eap_type == EAP_TYPE_NONE) {
00339                         int i;
00340                         for (i = 0; i < data->num_phase2_eap_types; i++) {
00341                                 if (data->phase2_eap_types[i] != *pos)
00342                                         continue;
00343 
00344                                 data->phase2_eap_type = *pos;
00345                                 wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
00346                                            "Phase 2 EAP method %d",
00347                                            data->phase2_eap_type);
00348                                 break;
00349                         }
00350                 }
00351                 if (*pos != data->phase2_eap_type || *pos == EAP_TYPE_NONE) {
00352                         if (eap_ttls_phase2_nak(sm, data, hdr, resp, resp_len))
00353                                 return -1;
00354                         break;
00355                 }
00356 
00357                 if (data->phase2_priv == NULL) {
00358                         data->phase2_method = eap_sm_get_eap_methods(*pos);
00359                         if (data->phase2_method) {
00360                                 sm->init_phase2 = 1;
00361                                 data->phase2_priv =
00362                                         data->phase2_method->init(sm);
00363                                 sm->init_phase2 = 0;
00364                         }
00365                 }
00366                 if (data->phase2_priv == NULL || data->phase2_method == NULL) {
00367                         wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize "
00368                                    "Phase 2 EAP method %d", *pos);
00369                         return -1;
00370                 }
00371                 memset(&iret, 0, sizeof(iret));
00372                 *resp = data->phase2_method->process(sm, data->phase2_priv,
00373                                                      &iret, (u8 *) hdr, len,
00374                                                      resp_len);
00375                 if ((iret.methodState == METHOD_DONE ||
00376                      iret.methodState == METHOD_MAY_CONT) &&
00377                     (iret.decision == DECISION_UNCOND_SUCC ||
00378                      iret.decision == DECISION_COND_SUCC ||
00379                      iret.decision == DECISION_FAIL)) {
00380                         ret->methodState = iret.methodState;
00381                         ret->decision = iret.decision;
00382                 }
00383                 break;
00384         }
00385 
00386         if (*resp == NULL &&
00387             (config->pending_req_identity || config->pending_req_password ||
00388              config->pending_req_otp)) {
00389                 return 0;
00390         }
00391 
00392         if (*resp == NULL)
00393                 return -1;
00394 
00395         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP encapsulate EAP Response",
00396                     *resp, *resp_len);
00397         return eap_ttls_avp_encapsulate(resp, resp_len,
00398                                         RADIUS_ATTR_EAP_MESSAGE, 1);
00399 }
00400 
00401 
00402 static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
00403                                             struct eap_ttls_data *data,
00404                                             struct eap_method_ret *ret,
00405                                             const struct eap_hdr *req,
00406                                             struct eap_hdr *hdr,
00407                                             u8 **resp, size_t *resp_len)
00408 {
00409         struct wpa_ssid *config = eap_get_config(sm);
00410         u8 *buf, *pos, *challenge, *username, *peer_challenge;
00411         size_t username_len;
00412         int i;
00413 
00414         wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request");
00415 
00416         /* MSCHAPv2 does not include optional domain name in the
00417          * challenge-response calculation, so remove domain prefix
00418          * (if present). */
00419         username = config->identity;
00420         username_len = config->identity_len;
00421         pos = username;
00422         for (i = 0; i < username_len; i++) {
00423                 if (username[i] == '\\') {
00424                         username_len -= i + 1;
00425                         username += i + 1;
00426                         break;
00427                 }
00428         }
00429 
00430         pos = buf = malloc(config->identity_len + 1000);
00431         if (buf == NULL) {
00432                 wpa_printf(MSG_ERROR,
00433                            "EAP-TTLS/MSCHAPV2: Failed to allocate memory");
00434                 return -1;
00435         }
00436 
00437         /* User-Name */
00438         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
00439                                config->identity, config->identity_len);
00440 
00441         /* MS-CHAP-Challenge */
00442         challenge = eap_tls_derive_key(sm, &data->ssl, "ttls challenge",
00443                                        EAP_TTLS_MSCHAPV2_CHALLENGE_LEN * 2 +
00444                                        1);
00445         if (challenge == NULL) {
00446                 free(buf);
00447                 wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
00448                            "implicit challenge");
00449                 return -1;
00450         }
00451         peer_challenge = challenge + 1 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;
00452 
00453         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE,
00454                                RADIUS_VENDOR_ID_MICROSOFT, 1,
00455                                challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
00456 
00457         /* MS-CHAP2-Response */
00458         pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_RESPONSE,
00459                                RADIUS_VENDOR_ID_MICROSOFT, 1,
00460                                EAP_TTLS_MSCHAPV2_RESPONSE_LEN);
00461         data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN];
00462         *pos++ = data->ident;
00463         *pos++ = 0; /* Flags */
00464         memcpy(pos, peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
00465         pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;
00466         memset(pos, 0, 8); /* Reserved, must be zero */
00467         pos += 8;
00468         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2: implicit auth_challenge",
00469                     challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
00470         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2: peer_challenge",
00471                     peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
00472         wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 username",
00473                           username, username_len);
00474         wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 password",
00475                               config->password, config->password_len);
00476         generate_nt_response(challenge, peer_challenge,
00477                              username, username_len,
00478                              config->password, config->password_len,
00479                              pos);
00480         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAPV2 response", pos, 24);
00481         generate_authenticator_response(config->password, config->password_len,
00482                                         peer_challenge, challenge,
00483                                         username, username_len,
00484                                         pos, data->auth_response);
00485         data->auth_response_valid = 1;
00486 
00487         pos += 24;
00488         free(challenge);
00489         AVP_PAD(buf, pos);
00490 
00491         *resp = buf;
00492         *resp_len = pos - buf;
00493 
00494         if (sm->workaround) {
00495                 /* At least FreeRADIUS seems to be terminating
00496                  * EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success
00497                  * packet. */
00498                 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: EAP workaround - "
00499                            "allow success without tunneled response");
00500                 ret->methodState = METHOD_MAY_CONT;
00501                 ret->decision = DECISION_COND_SUCC;
00502         }
00503 
00504         return 0;
00505 }
00506 
00507 
00508 static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
00509                                           struct eap_ttls_data *data,
00510                                           struct eap_method_ret *ret,
00511                                           const struct eap_hdr *req,
00512                                           struct eap_hdr *hdr,
00513                                           u8 **resp, size_t *resp_len)
00514 {
00515         struct wpa_ssid *config = eap_get_config(sm);
00516         u8 *buf, *pos, *challenge;
00517 
00518         wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request");
00519 
00520         pos = buf = malloc(config->identity_len + 1000);
00521         if (buf == NULL) {
00522                 wpa_printf(MSG_ERROR,
00523                            "EAP-TTLS/MSCHAP: Failed to allocate memory");
00524                 return -1;
00525         }
00526 
00527         /* User-Name */
00528         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
00529                                config->identity, config->identity_len);
00530 
00531         /* MS-CHAP-Challenge */
00532         challenge = eap_tls_derive_key(sm, &data->ssl, "ttls challenge",
00533                                        EAP_TLS_KEY_LEN);
00534         if (challenge == NULL) {
00535                 free(buf);
00536                 wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive "
00537                            "implicit challenge");
00538                 return -1;
00539         }
00540 
00541         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE,
00542                                RADIUS_VENDOR_ID_MICROSOFT, 1,
00543                                challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);
00544 
00545         /* MS-CHAP-Response */
00546         pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_RESPONSE,
00547                                RADIUS_VENDOR_ID_MICROSOFT, 1,
00548                                EAP_TTLS_MSCHAP_RESPONSE_LEN);
00549         data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN];
00550         *pos++ = data->ident;
00551         *pos++ = 1; /* Flags: Use NT style passwords */
00552         memset(pos, 0, 24); /* LM-Response */
00553         pos += 24;
00554         nt_challenge_response(challenge,
00555                               config->password, config->password_len,
00556                               pos); /* NT-Response */
00557         wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password",
00558                               config->password, config->password_len);
00559         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP implicit challenge",
00560                     challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);
00561         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24);
00562         pos += 24;
00563         free(challenge);
00564         AVP_PAD(buf, pos);
00565 
00566         *resp = buf;
00567         *resp_len = pos - buf;
00568 
00569         /* EAP-TTLS/MSCHAP does not provide tunneled success notification, so
00570          * assume that Phase2 succeeds. */
00571         ret->methodState = METHOD_DONE;
00572         ret->decision = DECISION_COND_SUCC;
00573 
00574         return 0;
00575 }
00576 
00577 
00578 static int eap_ttls_phase2_request_pap(struct eap_sm *sm,
00579                                        struct eap_ttls_data *data,
00580                                        struct eap_method_ret *ret,
00581                                        const struct eap_hdr *req,
00582                                        struct eap_hdr *hdr,
00583                                        u8 **resp, size_t *resp_len)
00584 {
00585         struct wpa_ssid *config = eap_get_config(sm);
00586         u8 *buf, *pos;
00587         size_t pad;
00588 
00589         wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request");
00590 
00591         pos = buf = malloc(config->identity_len + config->password_len + 100);
00592         if (buf == NULL) {
00593                 wpa_printf(MSG_ERROR,
00594                            "EAP-TTLS/PAP: Failed to allocate memory");
00595                 return -1;
00596         }
00597 
00598         /* User-Name */
00599         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
00600                                config->identity, config->identity_len);
00601 
00602         /* User-Password; in RADIUS, this is encrypted, but EAP-TTLS encrypts
00603          * the data, so no separate encryption is used in the AVP itself.
00604          * However, the password is padded to obfuscate its length. */
00605         pad = (16 - (config->password_len & 15)) & 15;
00606         pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1,
00607                                config->password_len + pad);
00608         memcpy(pos, config->password, config->password_len);
00609         pos += config->password_len;
00610         memset(pos, 0, pad);
00611         pos += pad;
00612         AVP_PAD(buf, pos);
00613 
00614         *resp = buf;
00615         *resp_len = pos - buf;
00616 
00617         /* EAP-TTLS/PAP does not provide tunneled success notification, so
00618          * assume that Phase2 succeeds. */
00619         ret->methodState = METHOD_DONE;
00620         ret->decision = DECISION_COND_SUCC;
00621 
00622         return 0;
00623 }
00624 
00625 
00626 static int eap_ttls_phase2_request_chap(struct eap_sm *sm,
00627                                         struct eap_ttls_data *data,
00628                                         struct eap_method_ret *ret,
00629                                         const struct eap_hdr *req,
00630                                         struct eap_hdr *hdr,
00631                                         u8 **resp, size_t *resp_len)
00632 {
00633         struct wpa_ssid *config = eap_get_config(sm);
00634         u8 *buf, *pos, *challenge;
00635         const u8 *addr[3];
00636         size_t len[3];
00637 
00638         wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request");
00639 
00640         pos = buf = malloc(config->identity_len + 1000);
00641         if (buf == NULL) {
00642                 wpa_printf(MSG_ERROR,
00643                            "EAP-TTLS/CHAP: Failed to allocate memory");
00644                 return -1;
00645         }
00646 
00647         /* User-Name */
00648         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
00649                                config->identity, config->identity_len);
00650 
00651         /* CHAP-Challenge */
00652         challenge = eap_tls_derive_key(sm, &data->ssl, "ttls challenge",
00653                                        EAP_TLS_KEY_LEN);
00654         if (challenge == NULL) {
00655                 free(buf);
00656                 wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "
00657                            "implicit challenge");
00658                 return -1;
00659         }
00660 
00661         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_CHAP_CHALLENGE, 0, 1,
00662                                challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);
00663 
00664         /* CHAP-Password */
00665         pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_CHAP_PASSWORD, 0, 1,
00666                                1 + EAP_TTLS_CHAP_PASSWORD_LEN);
00667         data->ident = challenge[EAP_TTLS_CHAP_CHALLENGE_LEN];
00668         *pos++ = data->ident;
00669 
00670         /* MD5(Ident + Password + Challenge) */
00671         addr[0] = &data->ident;
00672         len[0] = 1;
00673         addr[1] = config->password;
00674         len[1] = config->password_len;
00675         addr[2] = challenge;
00676         len[2] = EAP_TTLS_CHAP_CHALLENGE_LEN;
00677         md5_vector(3, addr, len, pos);
00678 
00679         wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username",
00680                           config->identity, config->identity_len);
00681         wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password",
00682                               config->password, config->password_len);
00683         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP implicit challenge",
00684                     challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);
00685         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password",
00686                     pos, EAP_TTLS_CHAP_PASSWORD_LEN);
00687         pos += EAP_TTLS_CHAP_PASSWORD_LEN;
00688         free(challenge);
00689         AVP_PAD(buf, pos);
00690 
00691         *resp = buf;
00692         *resp_len = pos - buf;
00693 
00694         /* EAP-TTLS/CHAP does not provide tunneled success notification, so
00695          * assume that Phase2 succeeds. */
00696         ret->methodState = METHOD_DONE;
00697         ret->decision = DECISION_COND_SUCC;
00698 
00699         return 0;
00700 }
00701 
00702 
00703 static int eap_ttls_phase2_request(struct eap_sm *sm,
00704                                    struct eap_ttls_data *data,
00705                                    struct eap_method_ret *ret,
00706                                    const struct eap_hdr *req,
00707                                    struct eap_hdr *hdr,
00708                                    u8 **resp, size_t *resp_len)
00709 {
00710         struct wpa_ssid *config = eap_get_config(sm);
00711         int res = 0;
00712 
00713         if (data->phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 ||
00714             data->phase2_type == EAP_TTLS_PHASE2_MSCHAP ||
00715             data->phase2_type == EAP_TTLS_PHASE2_PAP ||
00716             data->phase2_type == EAP_TTLS_PHASE2_CHAP) {
00717                 if (config->identity == NULL) {
00718                         wpa_printf(MSG_INFO,
00719                                    "EAP-TTLS: Identity not configured");
00720                         eap_sm_request_identity(sm, config);
00721                         if (config->password == NULL)
00722                                 eap_sm_request_password(sm, config);
00723                         return 0;
00724                 }
00725 
00726                 if (config->password == NULL) {
00727                         wpa_printf(MSG_INFO,
00728                                    "EAP-TTLS: Password not configured");
00729                         eap_sm_request_password(sm, config);
00730                         return 0;
00731                 }
00732         }
00733 
00734         switch (data->phase2_type) {
00735         case EAP_TTLS_PHASE2_EAP:
00736                 res = eap_ttls_phase2_request_eap(sm, data, ret, req, hdr,
00737                                                   resp, resp_len);
00738                 break;
00739         case EAP_TTLS_PHASE2_MSCHAPV2:
00740                 res = eap_ttls_phase2_request_mschapv2(sm, data, ret, req, hdr,
00741                                                        resp, resp_len);
00742                 break;
00743         case EAP_TTLS_PHASE2_MSCHAP:
00744                 res = eap_ttls_phase2_request_mschap(sm, data, ret, req, hdr,
00745                                                      resp, resp_len);
00746                 break;
00747         case EAP_TTLS_PHASE2_PAP:
00748                 res = eap_ttls_phase2_request_pap(sm, data, ret, req, hdr,
00749                                                   resp, resp_len);
00750                 break;
00751         case EAP_TTLS_PHASE2_CHAP:
00752                 res = eap_ttls_phase2_request_chap(sm, data, ret, req, hdr,
00753                                                    resp, resp_len);
00754                 break;
00755         default:
00756                 wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 - Unknown");
00757                 res = -1;
00758                 break;
00759         }
00760 
00761         if (res < 0) {
00762                 ret->methodState = METHOD_DONE;
00763                 ret->decision = DECISION_FAIL;
00764         }
00765 
00766         return res;
00767 }
00768 
00769 
00770 static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
00771                             struct eap_method_ret *ret,
00772                             const struct eap_hdr *req,
00773                             const u8 *in_data, size_t in_len,
00774                             u8 **out_data, size_t *out_len)
00775 {
00776         u8 *in_decrypted = NULL, *pos;
00777         int buf_len, len_decrypted = 0, len, left, retval = 0;
00778         struct eap_hdr *hdr = NULL;
00779         u8 *resp = NULL, *mschapv2 = NULL, *eapdata = NULL;
00780         size_t resp_len, eap_len = 0;
00781         struct ttls_avp *avp;
00782         u8 recv_response[20];
00783         int mschapv2_error = 0;
00784         struct wpa_ssid *config = eap_get_config(sm);
00785         const u8 *msg;
00786         size_t msg_len;
00787         int need_more_input;
00788 
00789         wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
00790                    " Phase 2", (unsigned long) in_len);
00791 
00792         if (data->pending_phase2_req) {
00793                 wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 request - "
00794                            "skip decryption and use old data");
00795                 /* Clear TLS reassembly state. */
00796                 free(data->ssl.tls_in);
00797                 data->ssl.tls_in = NULL;
00798                 data->ssl.tls_in_len = 0;
00799                 data->ssl.tls_in_left = 0;
00800                 data->ssl.tls_in_total = 0;
00801 
00802                 in_decrypted = data->pending_phase2_req;
00803                 data->pending_phase2_req = NULL;
00804                 len_decrypted = data->pending_phase2_req_len;
00805                 if (data->pending_phase2_req_len == 0) {
00806                         free(in_decrypted);
00807                         in_decrypted = NULL;
00808                         goto fake_req_identity;
00809                 }
00810                 goto continue_req;
00811         }
00812 
00813         if (in_len == 0 && data->phase2_start) {
00814                 data->phase2_start = 0;
00815                 /* EAP-TTLS does not use Phase2 on fast re-auth; this must be
00816                  * done only if TLS part was indeed resuming a previous
00817                  * session. Most Authentication Servers terminate EAP-TTLS
00818                  * before reaching this point, but some do not. Make
00819                  * wpa_supplicant stop phase 2 here, if needed. */
00820                 if (data->reauth &&
00821                     tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
00822                         wpa_printf(MSG_DEBUG, "EAP-TTLS: Session resumption - "
00823                                    "skip phase 2");
00824                         *out_data = eap_tls_build_ack(&data->ssl, out_len,
00825                                                       req->identifier,
00826                                                       EAP_TYPE_TTLS, 0);
00827                         ret->methodState = METHOD_DONE;
00828                         ret->decision = DECISION_UNCOND_SUCC;
00829                         data->phase2_success = 1;
00830                         return 0;
00831                 }
00832         fake_req_identity:
00833                 wpa_printf(MSG_DEBUG, "EAP-TTLS: empty data in beginning of "
00834                            "Phase 2 - use fake EAP-Request Identity");
00835                 buf_len = sizeof(*hdr) + 1;
00836                 in_decrypted = malloc(buf_len);
00837                 if (in_decrypted == NULL) {
00838                         wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate "
00839                                    "memory for fake EAP-Identity Request");
00840                         retval = -1;
00841                         goto done;
00842                 }
00843                 hdr = (struct eap_hdr *) in_decrypted;
00844                 hdr->code = EAP_CODE_REQUEST;
00845                 hdr->identifier = 0;
00846                 hdr->length = host_to_be16(sizeof(*hdr) + 1);
00847                 in_decrypted[sizeof(*hdr)] = EAP_TYPE_IDENTITY;
00848                 goto process_eap;
00849         }
00850 
00851         msg = eap_tls_data_reassemble(sm, &data->ssl, in_data, in_len,
00852                                       &msg_len, &need_more_input);
00853         if (msg == NULL)
00854                 return need_more_input ? 1 : -1;
00855 
00856         buf_len = in_len;
00857         if (data->ssl.tls_in_total > buf_len)
00858                 buf_len = data->ssl.tls_in_total;
00859         in_decrypted = malloc(buf_len);
00860         if (in_decrypted == NULL) {
00861                 free(data->ssl.tls_in);
00862                 data->ssl.tls_in = NULL;
00863                 data->ssl.tls_in_len = 0;
00864                 wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate memory "
00865                            "for decryption");
00866                 retval = -1;
00867                 goto done;
00868         }
00869 
00870         len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,
00871                                                msg, msg_len,
00872                                                in_decrypted, buf_len);
00873         free(data->ssl.tls_in);
00874         data->ssl.tls_in = NULL;
00875         data->ssl.tls_in_len = 0;
00876         if (len_decrypted < 0) {
00877                 wpa_printf(MSG_INFO, "EAP-TTLS: Failed to decrypt Phase 2 "
00878                            "data");
00879                 retval = -1;
00880                 goto done;
00881         }
00882 
00883 continue_req:
00884         data->phase2_start = 0;
00885 
00886         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 AVPs",
00887                     in_decrypted, len_decrypted);
00888         if (len_decrypted < sizeof(struct ttls_avp)) {
00889                 wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 AVP frame"
00890                            " len=%d expected %lu or more - dropped",
00891                            len_decrypted,
00892                            (unsigned long) sizeof(struct ttls_avp));
00893                 retval = -1;
00894                 goto done;
00895         }
00896 
00897         /* Parse AVPs */
00898         pos = in_decrypted;
00899         left = len_decrypted;
00900         mschapv2 = NULL;
00901 
00902         while (left > 0) {
00903                 u32 avp_code, avp_length, vendor_id = 0;
00904                 u8 avp_flags, *dpos;
00905                 size_t pad, dlen;
00906                 avp = (struct ttls_avp *) pos;
00907                 avp_code = be_to_host32(avp->avp_code);
00908                 avp_length = be_to_host32(avp->avp_length);
00909                 avp_flags = (avp_length >> 24) & 0xff;
00910                 avp_length &= 0xffffff;
00911                 wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x "
00912                            "length=%d", (int) avp_code, avp_flags,
00913                            (int) avp_length);
00914                 if (avp_length > left) {
00915                         wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow "
00916                                    "(len=%d, left=%d) - dropped",
00917                                    (int) avp_length, left);
00918                         retval = -1;
00919                         goto done;
00920                 }
00921                 dpos = (u8 *) (avp + 1);
00922                 dlen = avp_length - sizeof(*avp);
00923                 if (avp_flags & AVP_FLAGS_VENDOR) {
00924                         if (dlen < 4) {
00925                                 wpa_printf(MSG_WARNING, "EAP-TTLS: vendor AVP "
00926                                            "underflow");
00927                                 retval = -1;
00928                                 goto done;
00929                         }
00930                         vendor_id = be_to_host32(* (u32 *) dpos);
00931                         wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d",
00932                                    (int) vendor_id);
00933                         dpos += 4;
00934                         dlen -= 4;
00935                 }
00936 
00937                 wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen);
00938 
00939                 if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) {
00940                         wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message");
00941                         if (eapdata == NULL) {
00942                                 eapdata = malloc(dlen);
00943                                 if (eapdata == NULL) {
00944                                         retval = -1;
00945                                         wpa_printf(MSG_WARNING, "EAP-TTLS: "
00946                                                    "failed to allocate memory "
00947                                                    "for Phase 2 EAP data");
00948                                         goto done;
00949                                 }
00950                                 memcpy(eapdata, dpos, dlen);
00951                                 eap_len = dlen;
00952                         } else {
00953                                 u8 *neweap = realloc(eapdata, eap_len + dlen);
00954                                 if (neweap == NULL) {
00955                                         retval = -1;
00956                                         wpa_printf(MSG_WARNING, "EAP-TTLS: "
00957                                                    "failed to allocate memory "
00958                                                    "for Phase 2 EAP data");
00959                                         goto done;
00960                                 }
00961                                 memcpy(neweap + eap_len, dpos, dlen);
00962                                 eapdata = neweap;
00963                                 eap_len += dlen;
00964                         }
00965                 } else if (vendor_id == 0 &&
00966                            avp_code == RADIUS_ATTR_REPLY_MESSAGE) {
00967                         /* This is an optional message that can be displayed to
00968                          * the user. */
00969                         wpa_hexdump_ascii(MSG_DEBUG,
00970                                           "EAP-TTLS: AVP - Reply-Message",
00971                                           dpos, dlen);
00972                 } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
00973                            avp_code == RADIUS_ATTR_MS_CHAP2_SUCCESS) {
00974                         wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: "
00975                                           "MS-CHAP2-Success", dpos, dlen);
00976                         if (dlen != 43) {
00977                                 wpa_printf(MSG_WARNING, "EAP-TTLS: Unexpected "
00978                                            "MS-CHAP2-Success length "
00979                                            "(len=%lu, expected 43)",
00980                                            (unsigned long) dlen);
00981                                 retval = -1;
00982                                 break;
00983                         }
00984                         mschapv2 = dpos;
00985                 } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
00986                            avp_code == RADIUS_ATTR_MS_CHAP_ERROR) {
00987                         wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: "
00988                                           "MS-CHAP-Error", dpos, dlen);
00989                         mschapv2_error = 1;
00990                 } else if (avp_flags & AVP_FLAGS_MANDATORY) {
00991                         wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported "
00992                                    "mandatory AVP code %d vendor_id %d - "
00993                                    "dropped", (int) avp_code, (int) vendor_id);
00994                         retval = -1;
00995                         goto done;
00996                 } else {
00997                         wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported "
00998                                    "AVP code %d vendor_id %d",
00999                                    (int) avp_code, (int) vendor_id);
01000                 }
01001 
01002                 pad = (4 - (avp_length & 3)) & 3;
01003                 pos += avp_length + pad;
01004                 left -= avp_length + pad;
01005         }
01006 
01007         switch (data->phase2_type) {
01008         case EAP_TTLS_PHASE2_EAP:
01009                 if (eapdata == NULL) {
01010                         wpa_printf(MSG_WARNING, "EAP-TTLS: No EAP Message in "
01011                                    "the packet - dropped");
01012                         retval = -1;
01013                         goto done;
01014                 }
01015 
01016                 wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP",
01017                             eapdata, eap_len);
01018                 hdr = (struct eap_hdr *) eapdata;
01019 
01020                 if (eap_len < sizeof(*hdr)) {
01021                         wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 "
01022                                    "EAP frame (len=%lu, expected %lu or more) "
01023                                    "- dropped", (unsigned long) eap_len,
01024                                    (unsigned long) sizeof(*hdr));
01025                         retval = -1;
01026                         goto done;
01027                 }
01028                 len = be_to_host16(hdr->length);
01029                 if (len > eap_len) {
01030                         wpa_printf(MSG_INFO, "EAP-TTLS: Length mismatch in "
01031                                    "Phase 2 EAP frame (EAP hdr len=%d, EAP "
01032                                    "data len in AVP=%lu)", len,
01033                                    (unsigned long) eap_len);
01034                         retval = -1;
01035                         goto done;
01036                 }
01037                 wpa_printf(MSG_DEBUG, "EAP-TTLS: received Phase 2: code=%d "
01038                            "identifier=%d length=%d",
01039                            hdr->code, hdr->identifier, len);
01040         process_eap:
01041                 switch (hdr->code) {
01042                 case EAP_CODE_REQUEST:
01043                         if (eap_ttls_phase2_request(sm, data, ret, req, hdr,
01044                                                     &resp, &resp_len)) {
01045                                 wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 "
01046                                            "Request processing failed");
01047                                 retval = -1;
01048                                 goto done;
01049                         }
01050                         break;
01051                 default:
01052                         wpa_printf(MSG_INFO, "EAP-TTLS: Unexpected code=%d in "
01053                                    "Phase 2 EAP header", hdr->code);
01054                         retval = -1;
01055                         break;
01056                 }
01057                 break;
01058         case EAP_TTLS_PHASE2_MSCHAPV2:
01059                 if (mschapv2_error) {
01060                         wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Received "
01061                                    "MS-CHAP-Error - failed");
01062                         ret->methodState = METHOD_DONE;
01063                         ret->decision = DECISION_FAIL;
01064                         *out_data = eap_tls_build_ack(&data->ssl, out_len,
01065                                                       req->identifier,
01066                                                       EAP_TYPE_TTLS, 0);
01067                         break;
01068                 }
01069 
01070                 if (mschapv2 == NULL) {
01071                         wpa_printf(MSG_WARNING, "EAP-TTLS: no MS-CHAP2-Success"
01072                                    " AVP received for Phase2 MSCHAPV2");
01073                         retval = -1;
01074                         break;
01075                 }
01076                 if (mschapv2[0] != data->ident) {
01077                         wpa_printf(MSG_WARNING, "EAP-TTLS: Ident mismatch "
01078                                    "for Phase 2 MSCHAPV2 (received Ident "
01079                                    "0x%02x, expected 0x%02x)",
01080                                    mschapv2[0], data->ident);
01081                         retval = -1;
01082                         break;
01083                 }
01084                 if (!data->auth_response_valid ||
01085                     mschapv2[1] != 'S' || mschapv2[2] != '=' ||
01086                     hexstr2bin((char *) (mschapv2 + 3), recv_response, 20) ||
01087                     memcmp(data->auth_response, recv_response, 20) != 0) {
01088                         wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid "
01089                                    "authenticator response in Phase 2 "
01090                                    "MSCHAPV2 success request");
01091                         retval = -1;
01092                         break;
01093                 }
01094 
01095                 wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 MSCHAPV2 "
01096                            "authentication succeeded");
01097                 ret->methodState = METHOD_DONE;
01098                 ret->decision = DECISION_UNCOND_SUCC;
01099                 data->phase2_success = 1;
01100 
01101                 /* Reply with empty data; authentication server will reply
01102                  * with EAP-Success after this. */
01103                 retval = 1;
01104                 goto done;
01105         case EAP_TTLS_PHASE2_MSCHAP:
01106         case EAP_TTLS_PHASE2_PAP:
01107         case EAP_TTLS_PHASE2_CHAP:
01108                 /* EAP-TTLS/{MSCHAP,PAP,CHAP} should not send any TLS tunneled
01109                  * requests to the supplicant */
01110                 wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received unexpected "
01111                            "tunneled data");
01112                 retval = -1;
01113                 break;
01114         }
01115 
01116         if (resp) {
01117                 wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Encrypting Phase 2 data",
01118                                 resp, resp_len);
01119 
01120                 if (eap_ttls_encrypt(sm, data, req->identifier,
01121                                      resp, resp_len, out_data, out_len)) {
01122                         wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt "
01123                                    "a Phase 2 frame");
01124                 }
01125                 free(resp);
01126         } else if (config->pending_req_identity ||
01127                    config->pending_req_password ||
01128                    config->pending_req_otp ||
01129                    config->pending_req_new_password) {
01130                 free(data->pending_phase2_req);
01131                 data->pending_phase2_req = malloc(len_decrypted);
01132                 if (data->pending_phase2_req) {
01133                         memcpy(data->pending_phase2_req, in_decrypted,
01134                                len_decrypted);
01135                         data->pending_phase2_req_len = len_decrypted;
01136                 }
01137         }
01138 
01139 done:
01140         free(in_decrypted);
01141         free(eapdata);
01142 
01143         if (retval < 0) {
01144                 ret->methodState = METHOD_DONE;
01145                 ret->decision = DECISION_FAIL;
01146         }
01147 
01148         return retval;
01149 }
01150 
01151 
01152 static u8 * eap_ttls_process(struct eap_sm *sm, void *priv,
01153                              struct eap_method_ret *ret,
01154                              const u8 *reqData, size_t reqDataLen,
01155                              size_t *respDataLen)
01156 {
01157         const struct eap_hdr *req;
01158         size_t left;
01159         int res;
01160         u8 flags, *resp, id;
01161         const u8 *pos;
01162         struct eap_ttls_data *data = priv;
01163 
01164         pos = eap_tls_process_init(sm, &data->ssl, EAP_TYPE_TTLS, ret,
01165                                    reqData, reqDataLen, &left, &flags);
01166         if (pos == NULL)
01167                 return NULL;
01168         req = (const struct eap_hdr *) reqData;
01169         id = req->identifier;
01170 
01171         if (flags & EAP_TLS_FLAGS_START) {
01172                 wpa_printf(MSG_DEBUG, "EAP-TTLS: Start");
01173                 /* draft-ietf-pppext-eap-ttls-03.txt, Ch. 8.1:
01174                  * EAP-TTLS Start packet may, in a future specification, be
01175                  * allowed to contain data. Client based on this draft version
01176                  * must ignore such data but must not reject the Start packet.
01177                  */
01178                 left = 0;
01179         }
01180 
01181         resp = NULL;
01182         if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
01183             !data->resuming) {
01184                 res = eap_ttls_decrypt(sm, data, ret, req, pos, left,
01185                                        &resp, respDataLen);
01186         } else {
01187                 res = eap_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS, 0,
01188                                              id, pos, left,
01189                                              &resp, respDataLen);
01190 
01191                 if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
01192                         wpa_printf(MSG_DEBUG,
01193                                    "EAP-TTLS: TLS done, proceed to Phase 2");
01194                         if (data->resuming) {
01195                                 wpa_printf(MSG_DEBUG, "EAP-TTLS: fast reauth -"
01196                                            " may skip Phase 2");
01197                                 ret->decision = DECISION_COND_SUCC;
01198                                 ret->methodState = METHOD_MAY_CONT;
01199                         }
01200                         data->phase2_start = 1;
01201                         free(data->key_data);
01202                         data->key_data =
01203                                 eap_tls_derive_key(sm, &data->ssl,
01204                                                    "ttls keying material",
01205                                                    EAP_TLS_KEY_LEN);
01206                         if (data->key_data) {
01207                                 wpa_hexdump_key(MSG_DEBUG,
01208                                                 "EAP-TTLS: Derived key",
01209                                                 data->key_data,
01210                                                 EAP_TLS_KEY_LEN);
01211                         } else {
01212                                 wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to "
01213                                            "derive key");
01214                         }
01215 
01216                         if (*respDataLen == 0) {
01217                                 if (eap_ttls_decrypt(sm, data, ret, req, NULL,
01218                                                      0, &resp, respDataLen)) {
01219                                         wpa_printf(MSG_WARNING, "EAP-TTLS: "
01220                                                    "failed to process early "
01221                                                    "start for Phase 2");
01222                                 }
01223                                 res = 0;
01224                         }
01225                         data->resuming = 0;
01226                 }
01227         }
01228 
01229         if (ret->methodState == METHOD_DONE) {
01230                 ret->allowNotifications = FALSE;
01231                 if (ret->decision == DECISION_UNCOND_SUCC ||
01232                     ret->decision == DECISION_COND_SUCC) {
01233                         wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
01234                                    "completed successfully");
01235                         data->phase2_success = 1;
01236                 }
01237         } else if (sm->workaround && ret->methodState == METHOD_MAY_CONT &&
01238                    (ret->decision == DECISION_UNCOND_SUCC ||
01239                     ret->decision == DECISION_COND_SUCC)) {
01240                         wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
01241                                    "completed successfully (EAP workaround)");
01242                         data->phase2_success = 1;
01243         }
01244 
01245         if (res == 1) {
01246                 return eap_tls_build_ack(&data->ssl, respDataLen, id,
01247                                          EAP_TYPE_TTLS, 0);
01248         }
01249         return resp;
01250 }
01251 
01252 
01253 static Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv)
01254 {
01255         struct eap_ttls_data *data = priv;
01256         return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
01257                 data->phase2_success;
01258 }
01259 
01260 
01261 static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
01262 {
01263         struct eap_ttls_data *data = priv;
01264         free(data->pending_phase2_req);
01265         data->pending_phase2_req = NULL;
01266 }
01267 
01268 
01269 static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv)
01270 {
01271         struct eap_ttls_data *data = priv;
01272         free(data->key_data);
01273         data->key_data = NULL;
01274         if (eap_tls_reauth_init(sm, &data->ssl)) {
01275                 free(data);
01276                 return NULL;
01277         }
01278         data->phase2_start = 0;
01279         data->phase2_success = 0;
01280         data->resuming = 1;
01281         data->reauth = 1;
01282         return priv;
01283 }
01284 
01285 
01286 static int eap_ttls_get_status(struct eap_sm *sm, void *priv, char *buf,
01287                                size_t buflen, int verbose)
01288 {
01289         struct eap_ttls_data *data = priv;
01290         int len;
01291 
01292         len = eap_tls_status(sm, &data->ssl, buf, buflen, verbose);
01293         switch (data->phase2_type) {
01294         case EAP_TTLS_PHASE2_EAP:
01295                 len += snprintf(buf + len, buflen - len,
01296                                 "EAP-TTLS Phase2 method=EAP-%s\n",
01297                                 data->phase2_method ? data->phase2_method->name
01298                                 : "?");
01299                 break;
01300         case EAP_TTLS_PHASE2_MSCHAPV2:
01301                 len += snprintf(buf + len, buflen - len,
01302                                 "EAP-TTLS Phase2 method=MSCHAPV2\n");
01303                 break;
01304         case EAP_TTLS_PHASE2_MSCHAP:
01305                 len += snprintf(buf + len, buflen - len,
01306                                 "EAP-TTLS Phase2 method=MSCHAP\n");
01307                 break;
01308         case EAP_TTLS_PHASE2_PAP:
01309                 len += snprintf(buf + len, buflen - len,
01310                                 "EAP-TTLS Phase2 method=PAP\n");
01311                 break;
01312         case EAP_TTLS_PHASE2_CHAP:
01313                 len += snprintf(buf + len, buflen - len,
01314                                 "EAP-TTLS Phase2 method=CHAP\n");
01315                 break;
01316         }
01317 
01318         return len;
01319 }
01320 
01321 
01322 static Boolean eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv)
01323 {
01324         struct eap_ttls_data *data = priv;
01325         return data->key_data != NULL && data->phase2_success;
01326 }
01327 
01328 
01329 static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
01330 {
01331         struct eap_ttls_data *data = priv;
01332         u8 *key;
01333 
01334         if (data->key_data == NULL || !data->phase2_success)
01335                 return NULL;
01336 
01337         key = malloc(EAP_TLS_KEY_LEN);
01338         if (key == NULL)
01339                 return NULL;
01340 
01341         *len = EAP_TLS_KEY_LEN;
01342         memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
01343 
01344         return key;
01345 }
01346 
01347 
01348 const struct eap_method eap_method_ttls =
01349 {
01350         .method = EAP_TYPE_TTLS,
01351         .name = "TTLS",
01352         .init = eap_ttls_init,
01353         .deinit = eap_ttls_deinit,
01354         .process = eap_ttls_process,
01355         .isKeyAvailable = eap_ttls_isKeyAvailable,
01356         .getKey = eap_ttls_getKey,
01357         .get_status = eap_ttls_get_status,
01358         .has_reauth_data = eap_ttls_has_reauth_data,
01359         .deinit_for_reauth = eap_ttls_deinit_for_reauth,
01360         .init_for_reauth = eap_ttls_init_for_reauth,
01361 };
01362 

Generated on Sat May 6 21:13:36 2006 for wpa_supplicant by  doxygen 1.4.2