eap_ttls.c
Go to the documentation of this file.
00001 /*
00002  * EAP peer method: EAP-TTLS (RFC 5281)
00003  * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  *
00009  * Alternatively, this software may be distributed under the terms of BSD
00010  * license.
00011  *
00012  * See README and COPYING for more details.
00013  */
00014 
00015 #include "includes.h"
00016 
00017 #include "common.h"
00018 #include "crypto/ms_funcs.h"
00019 #include "crypto/sha1.h"
00020 #include "crypto/tls.h"
00021 #include "eap_common/chap.h"
00022 #include "eap_common/eap_ttls.h"
00023 #include "mschapv2.h"
00024 #include "eap_i.h"
00025 #include "eap_tls_common.h"
00026 #include "eap_config.h"
00027 
00028 
00029 /* Maximum supported TTLS version
00030  * 0 = RFC 5281
00031  * 1 = draft-funk-eap-ttls-v1-00.txt
00032  */
00033 #ifndef EAP_TTLS_VERSION
00034 #define EAP_TTLS_VERSION 0 /* TTLSv1 implementation is not yet complete */
00035 #endif /* EAP_TTLS_VERSION */
00036 
00037 
00038 #define MSCHAPV2_KEY_LEN 16
00039 #define MSCHAPV2_NT_RESPONSE_LEN 24
00040 
00041 
00042 static void eap_ttls_deinit(struct eap_sm *sm, void *priv);
00043 
00044 
00045 struct eap_ttls_data {
00046         struct eap_ssl_data ssl;
00047         int ssl_initialized;
00048 
00049         int ttls_version, force_ttls_version;
00050 
00051         const struct eap_method *phase2_method;
00052         void *phase2_priv;
00053         int phase2_success;
00054         int phase2_start;
00055 
00056         enum phase2_types {
00057                 EAP_TTLS_PHASE2_EAP,
00058                 EAP_TTLS_PHASE2_MSCHAPV2,
00059                 EAP_TTLS_PHASE2_MSCHAP,
00060                 EAP_TTLS_PHASE2_PAP,
00061                 EAP_TTLS_PHASE2_CHAP
00062         } phase2_type;
00063         struct eap_method_type phase2_eap_type;
00064         struct eap_method_type *phase2_eap_types;
00065         size_t num_phase2_eap_types;
00066 
00067         u8 auth_response[MSCHAPV2_AUTH_RESPONSE_LEN];
00068         int auth_response_valid;
00069         u8 master_key[MSCHAPV2_MASTER_KEY_LEN]; /* MSCHAPv2 master key */
00070         u8 ident;
00071         int resuming; /* starting a resumed session */
00072         int reauth; /* reauthentication */
00073         u8 *key_data;
00074 
00075         struct wpabuf *pending_phase2_req;
00076 
00077 #ifdef EAP_TNC
00078         int ready_for_tnc;
00079         int tnc_started;
00080 #endif /* EAP_TNC */
00081 };
00082 
00083 
00084 static void * eap_ttls_init(struct eap_sm *sm)
00085 {
00086         struct eap_ttls_data *data;
00087         struct eap_peer_config *config = eap_get_config(sm);
00088         char *selected;
00089 
00090         data = os_zalloc(sizeof(*data));
00091         if (data == NULL)
00092                 return NULL;
00093         data->ttls_version = EAP_TTLS_VERSION;
00094         data->force_ttls_version = -1;
00095         selected = "EAP";
00096         data->phase2_type = EAP_TTLS_PHASE2_EAP;
00097 
00098 #if EAP_TTLS_VERSION > 0
00099         if (config && config->phase1) {
00100                 const char *pos = os_strstr(config->phase1, "ttlsver=");
00101                 if (pos) {
00102                         data->force_ttls_version = atoi(pos + 8);
00103                         data->ttls_version = data->force_ttls_version;
00104                         wpa_printf(MSG_DEBUG, "EAP-TTLS: Forced TTLS version "
00105                                    "%d", data->force_ttls_version);
00106                 }
00107         }
00108 #endif /* EAP_TTLS_VERSION */
00109 
00110         if (config && config->phase2) {
00111                 if (os_strstr(config->phase2, "autheap=")) {
00112                         selected = "EAP";
00113                         data->phase2_type = EAP_TTLS_PHASE2_EAP;
00114                 } else if (os_strstr(config->phase2, "auth=MSCHAPV2")) {
00115                         selected = "MSCHAPV2";
00116                         data->phase2_type = EAP_TTLS_PHASE2_MSCHAPV2;
00117                 } else if (os_strstr(config->phase2, "auth=MSCHAP")) {
00118                         selected = "MSCHAP";
00119                         data->phase2_type = EAP_TTLS_PHASE2_MSCHAP;
00120                 } else if (os_strstr(config->phase2, "auth=PAP")) {
00121                         selected = "PAP";
00122                         data->phase2_type = EAP_TTLS_PHASE2_PAP;
00123                 } else if (os_strstr(config->phase2, "auth=CHAP")) {
00124                         selected = "CHAP";
00125                         data->phase2_type = EAP_TTLS_PHASE2_CHAP;
00126                 }
00127         }
00128         wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase2 type: %s", selected);
00129 
00130         if (data->phase2_type == EAP_TTLS_PHASE2_EAP) {
00131                 if (eap_peer_select_phase2_methods(config, "autheap=",
00132                                                    &data->phase2_eap_types,
00133                                                    &data->num_phase2_eap_types)
00134                     < 0) {
00135                         eap_ttls_deinit(sm, data);
00136                         return NULL;
00137                 }
00138 
00139                 data->phase2_eap_type.vendor = EAP_VENDOR_IETF;
00140                 data->phase2_eap_type.method = EAP_TYPE_NONE;
00141         }
00142 
00143 #if EAP_TTLS_VERSION > 0
00144         if (!(tls_capabilities(sm->ssl_ctx) & TLS_CAPABILITY_IA) &&
00145             data->ttls_version > 0) {
00146                 if (data->force_ttls_version > 0) {
00147                         wpa_printf(MSG_INFO, "EAP-TTLS: Forced TTLSv%d and "
00148                                    "TLS library does not support TLS/IA.",
00149                                    data->force_ttls_version);
00150                         eap_ttls_deinit(sm, data);
00151                         return NULL;
00152                 }
00153                 data->ttls_version = 0;
00154         }
00155 #endif /* EAP_TTLS_VERSION */
00156 
00157         return data;
00158 }
00159 
00160 
00161 static void eap_ttls_phase2_eap_deinit(struct eap_sm *sm,
00162                                        struct eap_ttls_data *data)
00163 {
00164         if (data->phase2_priv && data->phase2_method) {
00165                 data->phase2_method->deinit(sm, data->phase2_priv);
00166                 data->phase2_method = NULL;
00167                 data->phase2_priv = NULL;
00168         }
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         eap_ttls_phase2_eap_deinit(sm, data);
00178         os_free(data->phase2_eap_types);
00179         if (data->ssl_initialized)
00180                 eap_peer_tls_ssl_deinit(sm, &data->ssl);
00181         os_free(data->key_data);
00182         wpabuf_free(data->pending_phase2_req);
00183         os_free(data);
00184 }
00185 
00186 
00187 static u8 * eap_ttls_avp_hdr(u8 *avphdr, u32 avp_code, u32 vendor_id,
00188                              int mandatory, size_t len)
00189 {
00190         struct ttls_avp_vendor *avp;
00191         u8 flags;
00192         size_t hdrlen;
00193 
00194         avp = (struct ttls_avp_vendor *) avphdr;
00195         flags = mandatory ? AVP_FLAGS_MANDATORY : 0;
00196         if (vendor_id) {
00197                 flags |= AVP_FLAGS_VENDOR;
00198                 hdrlen = sizeof(*avp);
00199                 avp->vendor_id = host_to_be32(vendor_id);
00200         } else {
00201                 hdrlen = sizeof(struct ttls_avp);
00202         }
00203 
00204         avp->avp_code = host_to_be32(avp_code);
00205         avp->avp_length = host_to_be32((flags << 24) | (hdrlen + len));
00206 
00207         return avphdr + hdrlen;
00208 }
00209 
00210 
00211 static u8 * eap_ttls_avp_add(u8 *start, u8 *avphdr, u32 avp_code,
00212                              u32 vendor_id, int mandatory,
00213                              const u8 *data, size_t len)
00214 {
00215         u8 *pos;
00216         pos = eap_ttls_avp_hdr(avphdr, avp_code, vendor_id, mandatory, len);
00217         os_memcpy(pos, data, len);
00218         pos += len;
00219         AVP_PAD(start, pos);
00220         return pos;
00221 }
00222 
00223 
00224 static int eap_ttls_avp_encapsulate(struct wpabuf **resp, u32 avp_code,
00225                                     int mandatory)
00226 {
00227         struct wpabuf *msg;
00228         u8 *avp, *pos;
00229 
00230         msg = wpabuf_alloc(sizeof(struct ttls_avp) + wpabuf_len(*resp) + 4);
00231         if (msg == NULL) {
00232                 wpabuf_free(*resp);
00233                 *resp = NULL;
00234                 return -1;
00235         }
00236 
00237         avp = wpabuf_mhead(msg);
00238         pos = eap_ttls_avp_hdr(avp, avp_code, 0, mandatory, wpabuf_len(*resp));
00239         os_memcpy(pos, wpabuf_head(*resp), wpabuf_len(*resp));
00240         pos += wpabuf_len(*resp);
00241         AVP_PAD(avp, pos);
00242         wpabuf_free(*resp);
00243         wpabuf_put(msg, pos - avp);
00244         *resp = msg;
00245         return 0;
00246 }
00247 
00248 
00249 #if EAP_TTLS_VERSION > 0
00250 static int eap_ttls_ia_permute_inner_secret(struct eap_sm *sm,
00251                                             struct eap_ttls_data *data,
00252                                             const u8 *key, size_t key_len)
00253 {
00254         u8 *buf;
00255         size_t buf_len;
00256         int ret;
00257 
00258         if (key) {
00259                 buf_len = 2 + key_len;
00260                 buf = os_malloc(buf_len);
00261                 if (buf == NULL)
00262                         return -1;
00263                 WPA_PUT_BE16(buf, key_len);
00264                 os_memcpy(buf + 2, key, key_len);
00265         } else {
00266                 buf = NULL;
00267                 buf_len = 0;
00268         }
00269 
00270         wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Session keys for TLS/IA inner "
00271                         "secret permutation", buf, buf_len);
00272         ret = tls_connection_ia_permute_inner_secret(sm->ssl_ctx,
00273                                                      data->ssl.conn,
00274                                                      buf, buf_len);
00275         os_free(buf);
00276 
00277         return ret;
00278 }
00279 #endif /* EAP_TTLS_VERSION */
00280 
00281 
00282 static int eap_ttls_v0_derive_key(struct eap_sm *sm,
00283                                   struct eap_ttls_data *data)
00284 {
00285         os_free(data->key_data);
00286         data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
00287                                                  "ttls keying material",
00288                                                  EAP_TLS_KEY_LEN);
00289         if (!data->key_data) {
00290                 wpa_printf(MSG_INFO, "EAP-TTLS: Failed to derive key");
00291                 return -1;
00292         }
00293 
00294         wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
00295                         data->key_data, EAP_TLS_KEY_LEN);
00296 
00297         return 0;
00298 }
00299 
00300 
00301 #if EAP_TTLS_VERSION > 0
00302 static int eap_ttls_v1_derive_key(struct eap_sm *sm,
00303                                   struct eap_ttls_data *data)
00304 {
00305         struct tls_keys keys;
00306         u8 *rnd;
00307 
00308         os_free(data->key_data);
00309         data->key_data = NULL;
00310 
00311         os_memset(&keys, 0, sizeof(keys));
00312         if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
00313             keys.client_random == NULL || keys.server_random == NULL ||
00314             keys.inner_secret == NULL) {
00315                 wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
00316                            "client random, or server random to derive keying "
00317                            "material");
00318                 return -1;
00319         }
00320 
00321         rnd = os_malloc(keys.client_random_len + keys.server_random_len);
00322         data->key_data = os_malloc(EAP_TLS_KEY_LEN);
00323         if (rnd == NULL || data->key_data == NULL) {
00324                 wpa_printf(MSG_INFO, "EAP-TTLS: No memory for key derivation");
00325                 os_free(rnd);
00326                 os_free(data->key_data);
00327                 data->key_data = NULL;
00328                 return -1;
00329         }
00330         os_memcpy(rnd, keys.client_random, keys.client_random_len);
00331         os_memcpy(rnd + keys.client_random_len, keys.server_random,
00332                   keys.server_random_len);
00333 
00334         if (tls_prf(keys.inner_secret, keys.inner_secret_len,
00335                     "ttls v1 keying material", rnd, keys.client_random_len +
00336                     keys.server_random_len, data->key_data, EAP_TLS_KEY_LEN)) {
00337                 wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive key");
00338                 os_free(rnd);
00339                 os_free(data->key_data);
00340                 data->key_data = NULL;
00341                 return -1;
00342         }
00343 
00344         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: client/server random",
00345                     rnd, keys.client_random_len + keys.server_random_len);
00346         wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: TLS/IA inner secret",
00347                         keys.inner_secret, keys.inner_secret_len);
00348 
00349         os_free(rnd);
00350 
00351         wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived key",
00352                         data->key_data, EAP_TLS_KEY_LEN);
00353 
00354         return 0;
00355 }
00356 #endif /* EAP_TTLS_VERSION */
00357 
00358 
00359 static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
00360                                         struct eap_ttls_data *data, size_t len)
00361 {
00362 #if EAP_TTLS_VERSION > 0
00363         struct tls_keys keys;
00364         u8 *challenge, *rnd;
00365 #endif /* EAP_TTLS_VERSION */
00366 
00367         if (data->ttls_version == 0) {
00368                 return eap_peer_tls_derive_key(sm, &data->ssl,
00369                                                "ttls challenge", len);
00370         }
00371 
00372 #if EAP_TTLS_VERSION > 0
00373 
00374         os_memset(&keys, 0, sizeof(keys));
00375         if (tls_connection_get_keys(sm->ssl_ctx, data->ssl.conn, &keys) ||
00376             keys.client_random == NULL || keys.server_random == NULL ||
00377             keys.inner_secret == NULL) {
00378                 wpa_printf(MSG_INFO, "EAP-TTLS: Could not get inner secret, "
00379                            "client random, or server random to derive "
00380                            "implicit challenge");
00381                 return NULL;
00382         }
00383 
00384         rnd = os_malloc(keys.client_random_len + keys.server_random_len);
00385         challenge = os_malloc(len);
00386         if (rnd == NULL || challenge == NULL) {
00387                 wpa_printf(MSG_INFO, "EAP-TTLS: No memory for implicit "
00388                            "challenge derivation");
00389                 os_free(rnd);
00390                 os_free(challenge);
00391                 return NULL;
00392         }
00393         os_memcpy(rnd, keys.server_random, keys.server_random_len);
00394         os_memcpy(rnd + keys.server_random_len, keys.client_random,
00395                   keys.client_random_len);
00396 
00397         if (tls_prf(keys.inner_secret, keys.inner_secret_len,
00398                     "inner application challenge", rnd,
00399                     keys.client_random_len + keys.server_random_len,
00400                     challenge, len)) {
00401                 wpa_printf(MSG_DEBUG, "EAP-TTLS: Failed to derive implicit "
00402                            "challenge");
00403                 os_free(rnd);
00404                 os_free(challenge);
00405                 return NULL;
00406         }
00407 
00408         os_free(rnd);
00409 
00410         wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: Derived implicit challenge",
00411                         challenge, len);
00412 
00413         return challenge;
00414 
00415 #else /* EAP_TTLS_VERSION */
00416 
00417         return NULL;
00418 
00419 #endif /* EAP_TTLS_VERSION */
00420 }
00421 
00422 
00423 static void eap_ttlsv1_phase2_eap_finish(struct eap_sm *sm,
00424                                          struct eap_ttls_data *data,
00425                                          struct eap_method_ret *ret)
00426 {
00427 #if EAP_TTLS_VERSION > 0
00428         if (data->ttls_version > 0) {
00429                 const struct eap_method *m = data->phase2_method;
00430                 void *priv = data->phase2_priv;
00431 
00432                 /* TTLSv1 requires TLS/IA FinalPhaseFinished */
00433                 if (ret->decision == DECISION_UNCOND_SUCC)
00434                         ret->decision = DECISION_COND_SUCC;
00435                 ret->methodState = METHOD_CONT;
00436 
00437                 if (ret->decision == DECISION_COND_SUCC &&
00438                     m->isKeyAvailable && m->getKey &&
00439                     m->isKeyAvailable(sm, priv)) {
00440                         u8 *key;
00441                         size_t key_len;
00442                         key = m->getKey(sm, priv, &key_len);
00443                         if (key) {
00444                                 eap_ttls_ia_permute_inner_secret(
00445                                         sm, data, key, key_len);
00446                                 os_free(key);
00447                         }
00448                 }
00449         }
00450 #endif /* EAP_TTLS_VERSION */
00451 }
00452 
00453 
00454 static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data,
00455                                               u8 method)
00456 {
00457         size_t i;
00458         for (i = 0; i < data->num_phase2_eap_types; i++) {
00459                 if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF ||
00460                     data->phase2_eap_types[i].method != method)
00461                         continue;
00462 
00463                 data->phase2_eap_type.vendor =
00464                         data->phase2_eap_types[i].vendor;
00465                 data->phase2_eap_type.method =
00466                         data->phase2_eap_types[i].method;
00467                 wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
00468                            "Phase 2 EAP vendor %d method %d",
00469                            data->phase2_eap_type.vendor,
00470                            data->phase2_eap_type.method);
00471                 break;
00472         }
00473 }
00474 
00475 
00476 static int eap_ttls_phase2_eap_process(struct eap_sm *sm,
00477                                        struct eap_ttls_data *data,
00478                                        struct eap_method_ret *ret,
00479                                        struct eap_hdr *hdr, size_t len,
00480                                        struct wpabuf **resp)
00481 {
00482         struct wpabuf msg;
00483         struct eap_method_ret iret;
00484 
00485         os_memset(&iret, 0, sizeof(iret));
00486         wpabuf_set(&msg, hdr, len);
00487         *resp = data->phase2_method->process(sm, data->phase2_priv, &iret,
00488                                              &msg);
00489         if ((iret.methodState == METHOD_DONE ||
00490              iret.methodState == METHOD_MAY_CONT) &&
00491             (iret.decision == DECISION_UNCOND_SUCC ||
00492              iret.decision == DECISION_COND_SUCC ||
00493              iret.decision == DECISION_FAIL)) {
00494                 ret->methodState = iret.methodState;
00495                 ret->decision = iret.decision;
00496         }
00497         eap_ttlsv1_phase2_eap_finish(sm, data, ret);
00498 
00499         return 0;
00500 }
00501 
00502 
00503 static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
00504                                               struct eap_ttls_data *data,
00505                                               struct eap_method_ret *ret,
00506                                               struct eap_hdr *hdr, size_t len,
00507                                               u8 method, struct wpabuf **resp)
00508 {
00509 #ifdef EAP_TNC
00510         if (data->tnc_started && data->phase2_method &&
00511             data->phase2_priv && method == EAP_TYPE_TNC &&
00512             data->phase2_eap_type.method == EAP_TYPE_TNC)
00513                 return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len,
00514                                                    resp);
00515 
00516         if (data->ready_for_tnc && !data->tnc_started &&
00517             method == EAP_TYPE_TNC) {
00518                 wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed "
00519                            "EAP method");
00520                 data->tnc_started = 1;
00521         }
00522 
00523         if (data->tnc_started) {
00524                 if (data->phase2_eap_type.vendor != EAP_VENDOR_IETF ||
00525                     data->phase2_eap_type.method == EAP_TYPE_TNC) {
00526                         wpa_printf(MSG_DEBUG, "EAP-TTLS: Unexpected EAP "
00527                                    "type %d for TNC", method);
00528                         return -1;
00529                 }
00530 
00531                 data->phase2_eap_type.vendor = EAP_VENDOR_IETF;
00532                 data->phase2_eap_type.method = method;
00533                 wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
00534                            "Phase 2 EAP vendor %d method %d (TNC)",
00535                            data->phase2_eap_type.vendor,
00536                            data->phase2_eap_type.method);
00537 
00538                 if (data->phase2_type == EAP_TTLS_PHASE2_EAP)
00539                         eap_ttls_phase2_eap_deinit(sm, data);
00540         }
00541 #endif /* EAP_TNC */
00542 
00543         if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF &&
00544             data->phase2_eap_type.method == EAP_TYPE_NONE)
00545                 eap_ttls_phase2_select_eap_method(data, method);
00546 
00547         if (method != data->phase2_eap_type.method || method == EAP_TYPE_NONE)
00548         {
00549                 if (eap_peer_tls_phase2_nak(data->phase2_eap_types,
00550                                             data->num_phase2_eap_types,
00551                                             hdr, resp))
00552                         return -1;
00553                 return 0;
00554         }
00555 
00556         if (data->phase2_priv == NULL) {
00557                 data->phase2_method = eap_peer_get_eap_method(
00558                         EAP_VENDOR_IETF, method);
00559                 if (data->phase2_method) {
00560                         sm->init_phase2 = 1;
00561                         data->phase2_priv = data->phase2_method->init(sm);
00562                         sm->init_phase2 = 0;
00563                 }
00564         }
00565         if (data->phase2_priv == NULL || data->phase2_method == NULL) {
00566                 wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize "
00567                            "Phase 2 EAP method %d", method);
00568                 return -1;
00569         }
00570 
00571         return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, resp);
00572 }
00573 
00574 
00575 static int eap_ttls_phase2_request_eap(struct eap_sm *sm,
00576                                        struct eap_ttls_data *data,
00577                                        struct eap_method_ret *ret,
00578                                        struct eap_hdr *hdr,
00579                                        struct wpabuf **resp)
00580 {
00581         size_t len = be_to_host16(hdr->length);
00582         u8 *pos;
00583         struct eap_peer_config *config = eap_get_config(sm);
00584 
00585         if (len <= sizeof(struct eap_hdr)) {
00586                 wpa_printf(MSG_INFO, "EAP-TTLS: too short "
00587                            "Phase 2 request (len=%lu)", (unsigned long) len);
00588                 return -1;
00589         }
00590         pos = (u8 *) (hdr + 1);
00591         wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP Request: type=%d", *pos);
00592         switch (*pos) {
00593         case EAP_TYPE_IDENTITY:
00594                 *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
00595                 break;
00596         default:
00597                 if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len,
00598                                                        *pos, resp) < 0)
00599                         return -1;
00600                 break;
00601         }
00602 
00603         if (*resp == NULL &&
00604             (config->pending_req_identity || config->pending_req_password ||
00605              config->pending_req_otp)) {
00606                 return 0;
00607         }
00608 
00609         if (*resp == NULL)
00610                 return -1;
00611 
00612         wpa_hexdump_buf(MSG_DEBUG, "EAP-TTLS: AVP encapsulate EAP Response",
00613                         *resp);
00614         return eap_ttls_avp_encapsulate(resp, RADIUS_ATTR_EAP_MESSAGE, 1);
00615 }
00616 
00617 
00618 static void eap_ttlsv1_permute_inner(struct eap_sm *sm,
00619                                      struct eap_ttls_data *data)
00620 {
00621 #if EAP_TTLS_VERSION > 0
00622         u8 session_key[2 * MSCHAPV2_KEY_LEN];
00623 
00624         if (data->ttls_version == 0)
00625                 return;
00626 
00627         get_asymetric_start_key(data->master_key, session_key,
00628                                 MSCHAPV2_KEY_LEN, 0, 0);
00629         get_asymetric_start_key(data->master_key,
00630                                 session_key + MSCHAPV2_KEY_LEN,
00631                                 MSCHAPV2_KEY_LEN, 1, 0);
00632         eap_ttls_ia_permute_inner_secret(sm, data, session_key,
00633                                          sizeof(session_key));
00634 #endif /* EAP_TTLS_VERSION */
00635 }
00636 
00637 
00638 static int eap_ttls_phase2_request_mschapv2(struct eap_sm *sm,
00639                                             struct eap_ttls_data *data,
00640                                             struct eap_method_ret *ret,
00641                                             struct wpabuf **resp)
00642 {
00643         struct wpabuf *msg;
00644         u8 *buf, *pos, *challenge, *peer_challenge;
00645         const u8 *identity, *password;
00646         size_t identity_len, password_len;
00647         int pwhash;
00648 
00649         wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAPV2 Request");
00650 
00651         identity = eap_get_config_identity(sm, &identity_len);
00652         password = eap_get_config_password2(sm, &password_len, &pwhash);
00653         if (identity == NULL || password == NULL)
00654                 return -1;
00655 
00656         msg = wpabuf_alloc(identity_len + 1000);
00657         if (msg == NULL) {
00658                 wpa_printf(MSG_ERROR,
00659                            "EAP-TTLS/MSCHAPV2: Failed to allocate memory");
00660                 return -1;
00661         }
00662         pos = buf = wpabuf_mhead(msg);
00663 
00664         /* User-Name */
00665         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
00666                                identity, identity_len);
00667 
00668         /* MS-CHAP-Challenge */
00669         challenge = eap_ttls_implicit_challenge(
00670                 sm, data, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 1);
00671         if (challenge == NULL) {
00672                 wpabuf_free(msg);
00673                 wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
00674                            "implicit challenge");
00675                 return -1;
00676         }
00677         peer_challenge = challenge + 1 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;
00678 
00679         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE,
00680                                RADIUS_VENDOR_ID_MICROSOFT, 1,
00681                                challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
00682 
00683         /* MS-CHAP2-Response */
00684         pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP2_RESPONSE,
00685                                RADIUS_VENDOR_ID_MICROSOFT, 1,
00686                                EAP_TTLS_MSCHAPV2_RESPONSE_LEN);
00687         data->ident = challenge[EAP_TTLS_MSCHAPV2_CHALLENGE_LEN];
00688         *pos++ = data->ident;
00689         *pos++ = 0; /* Flags */
00690         os_memcpy(pos, peer_challenge, EAP_TTLS_MSCHAPV2_CHALLENGE_LEN);
00691         pos += EAP_TTLS_MSCHAPV2_CHALLENGE_LEN;
00692         os_memset(pos, 0, 8); /* Reserved, must be zero */
00693         pos += 8;
00694         if (mschapv2_derive_response(identity, identity_len, password,
00695                                      password_len, pwhash, challenge,
00696                                      peer_challenge, pos, data->auth_response,
00697                                      data->master_key)) {
00698                 wpabuf_free(msg);
00699                 wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAPV2: Failed to derive "
00700                            "response");
00701                 return -1;
00702         }
00703         data->auth_response_valid = 1;
00704 
00705         eap_ttlsv1_permute_inner(sm, data);
00706 
00707         pos += 24;
00708         os_free(challenge);
00709         AVP_PAD(buf, pos);
00710 
00711         wpabuf_put(msg, pos - buf);
00712         *resp = msg;
00713 
00714         if (sm->workaround && data->ttls_version == 0) {
00715                 /* At least FreeRADIUS seems to be terminating
00716                  * EAP-TTLS/MSHCAPV2 without the expected MS-CHAP-v2 Success
00717                  * packet. */
00718                 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: EAP workaround - "
00719                            "allow success without tunneled response");
00720                 ret->methodState = METHOD_MAY_CONT;
00721                 ret->decision = DECISION_COND_SUCC;
00722         }
00723 
00724         return 0;
00725 }
00726 
00727 
00728 static int eap_ttls_phase2_request_mschap(struct eap_sm *sm,
00729                                           struct eap_ttls_data *data,
00730                                           struct eap_method_ret *ret,
00731                                           struct wpabuf **resp)
00732 {
00733         struct wpabuf *msg;
00734         u8 *buf, *pos, *challenge;
00735         const u8 *identity, *password;
00736         size_t identity_len, password_len;
00737         int pwhash;
00738 
00739         wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 MSCHAP Request");
00740 
00741         identity = eap_get_config_identity(sm, &identity_len);
00742         password = eap_get_config_password2(sm, &password_len, &pwhash);
00743         if (identity == NULL || password == NULL)
00744                 return -1;
00745 
00746         msg = wpabuf_alloc(identity_len + 1000);
00747         if (msg == NULL) {
00748                 wpa_printf(MSG_ERROR,
00749                            "EAP-TTLS/MSCHAP: Failed to allocate memory");
00750                 return -1;
00751         }
00752         pos = buf = wpabuf_mhead(msg);
00753 
00754         /* User-Name */
00755         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
00756                                identity, identity_len);
00757 
00758         /* MS-CHAP-Challenge */
00759         challenge = eap_ttls_implicit_challenge(
00760                 sm, data, EAP_TTLS_MSCHAP_CHALLENGE_LEN + 1);
00761         if (challenge == NULL) {
00762                 wpabuf_free(msg);
00763                 wpa_printf(MSG_ERROR, "EAP-TTLS/MSCHAP: Failed to derive "
00764                            "implicit challenge");
00765                 return -1;
00766         }
00767 
00768         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_MS_CHAP_CHALLENGE,
00769                                RADIUS_VENDOR_ID_MICROSOFT, 1,
00770                                challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);
00771 
00772         /* MS-CHAP-Response */
00773         pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_MS_CHAP_RESPONSE,
00774                                RADIUS_VENDOR_ID_MICROSOFT, 1,
00775                                EAP_TTLS_MSCHAP_RESPONSE_LEN);
00776         data->ident = challenge[EAP_TTLS_MSCHAP_CHALLENGE_LEN];
00777         *pos++ = data->ident;
00778         *pos++ = 1; /* Flags: Use NT style passwords */
00779         os_memset(pos, 0, 24); /* LM-Response */
00780         pos += 24;
00781         if (pwhash) {
00782                 challenge_response(challenge, password, pos); /* NT-Response */
00783                 wpa_hexdump_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password hash",
00784                                 password, 16);
00785         } else {
00786                 nt_challenge_response(challenge, password, password_len,
00787                                       pos); /* NT-Response */
00788                 wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: MSCHAP password",
00789                                       password, password_len);
00790         }
00791         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP implicit challenge",
00792                     challenge, EAP_TTLS_MSCHAP_CHALLENGE_LEN);
00793         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: MSCHAP response", pos, 24);
00794         pos += 24;
00795         os_free(challenge);
00796         AVP_PAD(buf, pos);
00797 
00798         wpabuf_put(msg, pos - buf);
00799         *resp = msg;
00800 
00801         if (data->ttls_version > 0) {
00802                 /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,
00803                  * so do not allow connection to be terminated yet. */
00804                 ret->methodState = METHOD_CONT;
00805                 ret->decision = DECISION_COND_SUCC;
00806         } else {
00807                 /* EAP-TTLS/MSCHAP does not provide tunneled success
00808                  * notification, so assume that Phase2 succeeds. */
00809                 ret->methodState = METHOD_DONE;
00810                 ret->decision = DECISION_COND_SUCC;
00811         }
00812 
00813         return 0;
00814 }
00815 
00816 
00817 static int eap_ttls_phase2_request_pap(struct eap_sm *sm,
00818                                        struct eap_ttls_data *data,
00819                                        struct eap_method_ret *ret,
00820                                        struct wpabuf **resp)
00821 {
00822         struct wpabuf *msg;
00823         u8 *buf, *pos;
00824         size_t pad;
00825         const u8 *identity, *password;
00826         size_t identity_len, password_len;
00827 
00828         wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 PAP Request");
00829 
00830         identity = eap_get_config_identity(sm, &identity_len);
00831         password = eap_get_config_password(sm, &password_len);
00832         if (identity == NULL || password == NULL)
00833                 return -1;
00834 
00835         msg = wpabuf_alloc(identity_len + password_len + 100);
00836         if (msg == NULL) {
00837                 wpa_printf(MSG_ERROR,
00838                            "EAP-TTLS/PAP: Failed to allocate memory");
00839                 return -1;
00840         }
00841         pos = buf = wpabuf_mhead(msg);
00842 
00843         /* User-Name */
00844         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
00845                                identity, identity_len);
00846 
00847         /* User-Password; in RADIUS, this is encrypted, but EAP-TTLS encrypts
00848          * the data, so no separate encryption is used in the AVP itself.
00849          * However, the password is padded to obfuscate its length. */
00850         pad = password_len == 0 ? 16 : (16 - (password_len & 15)) & 15;
00851         pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_USER_PASSWORD, 0, 1,
00852                                password_len + pad);
00853         os_memcpy(pos, password, password_len);
00854         pos += password_len;
00855         os_memset(pos, 0, pad);
00856         pos += pad;
00857         AVP_PAD(buf, pos);
00858 
00859         wpabuf_put(msg, pos - buf);
00860         *resp = msg;
00861 
00862         if (data->ttls_version > 0) {
00863                 /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,
00864                  * so do not allow connection to be terminated yet. */
00865                 ret->methodState = METHOD_CONT;
00866                 ret->decision = DECISION_COND_SUCC;
00867         } else {
00868                 /* EAP-TTLS/PAP does not provide tunneled success notification,
00869                  * so assume that Phase2 succeeds. */
00870                 ret->methodState = METHOD_DONE;
00871                 ret->decision = DECISION_COND_SUCC;
00872         }
00873 
00874         return 0;
00875 }
00876 
00877 
00878 static int eap_ttls_phase2_request_chap(struct eap_sm *sm,
00879                                         struct eap_ttls_data *data,
00880                                         struct eap_method_ret *ret,
00881                                         struct wpabuf **resp)
00882 {
00883         struct wpabuf *msg;
00884         u8 *buf, *pos, *challenge;
00885         const u8 *identity, *password;
00886         size_t identity_len, password_len;
00887 
00888         wpa_printf(MSG_DEBUG, "EAP-TTLS: Phase 2 CHAP Request");
00889 
00890         identity = eap_get_config_identity(sm, &identity_len);
00891         password = eap_get_config_password(sm, &password_len);
00892         if (identity == NULL || password == NULL)
00893                 return -1;
00894 
00895         msg = wpabuf_alloc(identity_len + 1000);
00896         if (msg == NULL) {
00897                 wpa_printf(MSG_ERROR,
00898                            "EAP-TTLS/CHAP: Failed to allocate memory");
00899                 return -1;
00900         }
00901         pos = buf = wpabuf_mhead(msg);
00902 
00903         /* User-Name */
00904         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_USER_NAME, 0, 1,
00905                                identity, identity_len);
00906 
00907         /* CHAP-Challenge */
00908         challenge = eap_ttls_implicit_challenge(
00909                 sm, data, EAP_TTLS_CHAP_CHALLENGE_LEN + 1);
00910         if (challenge == NULL) {
00911                 wpabuf_free(msg);
00912                 wpa_printf(MSG_ERROR, "EAP-TTLS/CHAP: Failed to derive "
00913                            "implicit challenge");
00914                 return -1;
00915         }
00916 
00917         pos = eap_ttls_avp_add(buf, pos, RADIUS_ATTR_CHAP_CHALLENGE, 0, 1,
00918                                challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);
00919 
00920         /* CHAP-Password */
00921         pos = eap_ttls_avp_hdr(pos, RADIUS_ATTR_CHAP_PASSWORD, 0, 1,
00922                                1 + EAP_TTLS_CHAP_PASSWORD_LEN);
00923         data->ident = challenge[EAP_TTLS_CHAP_CHALLENGE_LEN];
00924         *pos++ = data->ident;
00925 
00926         /* MD5(Ident + Password + Challenge) */
00927         chap_md5(data->ident, password, password_len, challenge,
00928                  EAP_TTLS_CHAP_CHALLENGE_LEN, pos);
00929 
00930         wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: CHAP username",
00931                           identity, identity_len);
00932         wpa_hexdump_ascii_key(MSG_DEBUG, "EAP-TTLS: CHAP password",
00933                               password, password_len);
00934         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP implicit challenge",
00935                     challenge, EAP_TTLS_CHAP_CHALLENGE_LEN);
00936         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: CHAP password",
00937                     pos, EAP_TTLS_CHAP_PASSWORD_LEN);
00938         pos += EAP_TTLS_CHAP_PASSWORD_LEN;
00939         os_free(challenge);
00940         AVP_PAD(buf, pos);
00941 
00942         wpabuf_put(msg, pos - buf);
00943         *resp = msg;
00944 
00945         if (data->ttls_version > 0) {
00946                 /* EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report success,
00947                  * so do not allow connection to be terminated yet. */
00948                 ret->methodState = METHOD_CONT;
00949                 ret->decision = DECISION_COND_SUCC;
00950         } else {
00951                 /* EAP-TTLS/CHAP does not provide tunneled success
00952                  * notification, so assume that Phase2 succeeds. */
00953                 ret->methodState = METHOD_DONE;
00954                 ret->decision = DECISION_COND_SUCC;
00955         }
00956 
00957         return 0;
00958 }
00959 
00960 
00961 static int eap_ttls_phase2_request(struct eap_sm *sm,
00962                                    struct eap_ttls_data *data,
00963                                    struct eap_method_ret *ret,
00964                                    struct eap_hdr *hdr,
00965                                    struct wpabuf **resp)
00966 {
00967         int res = 0;
00968         size_t len;
00969         enum phase2_types phase2_type = data->phase2_type;
00970 
00971 #ifdef EAP_TNC
00972         if (data->tnc_started) {
00973                 wpa_printf(MSG_DEBUG, "EAP-TTLS: Processing TNC");
00974                 phase2_type = EAP_TTLS_PHASE2_EAP;
00975         }
00976 #endif /* EAP_TNC */
00977 
00978         if (phase2_type == EAP_TTLS_PHASE2_MSCHAPV2 ||
00979             phase2_type == EAP_TTLS_PHASE2_MSCHAP ||
00980             phase2_type == EAP_TTLS_PHASE2_PAP ||
00981             phase2_type == EAP_TTLS_PHASE2_CHAP) {
00982                 if (eap_get_config_identity(sm, &len) == NULL) {
00983                         wpa_printf(MSG_INFO,
00984                                    "EAP-TTLS: Identity not configured");
00985                         eap_sm_request_identity(sm);
00986                         if (eap_get_config_password(sm, &len) == NULL)
00987                                 eap_sm_request_password(sm);
00988                         return 0;
00989                 }
00990 
00991                 if (eap_get_config_password(sm, &len) == NULL) {
00992                         wpa_printf(MSG_INFO,
00993                                    "EAP-TTLS: Password not configured");
00994                         eap_sm_request_password(sm);
00995                         return 0;
00996                 }
00997         }
00998 
00999         switch (phase2_type) {
01000         case EAP_TTLS_PHASE2_EAP:
01001                 res = eap_ttls_phase2_request_eap(sm, data, ret, hdr, resp);
01002                 break;
01003         case EAP_TTLS_PHASE2_MSCHAPV2:
01004                 res = eap_ttls_phase2_request_mschapv2(sm, data, ret, resp);
01005                 break;
01006         case EAP_TTLS_PHASE2_MSCHAP:
01007                 res = eap_ttls_phase2_request_mschap(sm, data, ret, resp);
01008                 break;
01009         case EAP_TTLS_PHASE2_PAP:
01010                 res = eap_ttls_phase2_request_pap(sm, data, ret, resp);
01011                 break;
01012         case EAP_TTLS_PHASE2_CHAP:
01013                 res = eap_ttls_phase2_request_chap(sm, data, ret, resp);
01014                 break;
01015         default:
01016                 wpa_printf(MSG_ERROR, "EAP-TTLS: Phase 2 - Unknown");
01017                 res = -1;
01018                 break;
01019         }
01020 
01021         if (res < 0) {
01022                 ret->methodState = METHOD_DONE;
01023                 ret->decision = DECISION_FAIL;
01024         }
01025 
01026         return res;
01027 }
01028 
01029 
01030 #if EAP_TTLS_VERSION > 0
01031 static struct wpabuf * eap_ttls_build_phase_finished(
01032         struct eap_sm *sm, struct eap_ttls_data *data, int id, int final)
01033 {
01034         struct wpabuf *req, *buf;
01035 
01036         buf = tls_connection_ia_send_phase_finished(sm->ssl_ctx,
01037                                                     data->ssl.conn,
01038                                                     final);
01039         if (buf == NULL)
01040                 return NULL;
01041 
01042         req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TTLS,
01043                             1 + wpabuf_len(buf),
01044                             EAP_CODE_RESPONSE, id);
01045         if (req == NULL) {
01046                 wpabuf_free(buf);
01047                 return NULL;
01048         }
01049 
01050         wpabuf_put_u8(req, data->ttls_version);
01051         wpabuf_put_buf(req, buf);
01052         wpabuf_free(buf);
01053         eap_update_len(req);
01054 
01055         return req;
01056 }
01057 #endif /* EAP_TTLS_VERSION */
01058 
01059 
01060 struct ttls_parse_avp {
01061         u8 *mschapv2;
01062         u8 *eapdata;
01063         size_t eap_len;
01064         int mschapv2_error;
01065 };
01066 
01067 
01068 static int eap_ttls_parse_attr_eap(const u8 *dpos, size_t dlen,
01069                                    struct ttls_parse_avp *parse)
01070 {
01071         wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP - EAP Message");
01072         if (parse->eapdata == NULL) {
01073                 parse->eapdata = os_malloc(dlen);
01074                 if (parse->eapdata == NULL) {
01075                         wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate "
01076                                    "memory for Phase 2 EAP data");
01077                         return -1;
01078                 }
01079                 os_memcpy(parse->eapdata, dpos, dlen);
01080                 parse->eap_len = dlen;
01081         } else {
01082                 u8 *neweap = os_realloc(parse->eapdata, parse->eap_len + dlen);
01083                 if (neweap == NULL) {
01084                         wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to allocate "
01085                                    "memory for Phase 2 EAP data");
01086                         return -1;
01087                 }
01088                 os_memcpy(neweap + parse->eap_len, dpos, dlen);
01089                 parse->eapdata = neweap;
01090                 parse->eap_len += dlen;
01091         }
01092 
01093         return 0;
01094 }
01095 
01096 
01097 static int eap_ttls_parse_avp(u8 *pos, size_t left,
01098                               struct ttls_parse_avp *parse)
01099 {
01100         struct ttls_avp *avp;
01101         u32 avp_code, avp_length, vendor_id = 0;
01102         u8 avp_flags, *dpos;
01103         size_t dlen;
01104 
01105         avp = (struct ttls_avp *) pos;
01106         avp_code = be_to_host32(avp->avp_code);
01107         avp_length = be_to_host32(avp->avp_length);
01108         avp_flags = (avp_length >> 24) & 0xff;
01109         avp_length &= 0xffffff;
01110         wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP: code=%d flags=0x%02x "
01111                    "length=%d", (int) avp_code, avp_flags,
01112                    (int) avp_length);
01113 
01114         if (avp_length > left) {
01115                 wpa_printf(MSG_WARNING, "EAP-TTLS: AVP overflow "
01116                            "(len=%d, left=%lu) - dropped",
01117                            (int) avp_length, (unsigned long) left);
01118                 return -1;
01119         }
01120 
01121         if (avp_length < sizeof(*avp)) {
01122                 wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid AVP length %d",
01123                            avp_length);
01124                 return -1;
01125         }
01126 
01127         dpos = (u8 *) (avp + 1);
01128         dlen = avp_length - sizeof(*avp);
01129         if (avp_flags & AVP_FLAGS_VENDOR) {
01130                 if (dlen < 4) {
01131                         wpa_printf(MSG_WARNING, "EAP-TTLS: Vendor AVP "
01132                                    "underflow");
01133                         return -1;
01134                 }
01135                 vendor_id = WPA_GET_BE32(dpos);
01136                 wpa_printf(MSG_DEBUG, "EAP-TTLS: AVP vendor_id %d",
01137                            (int) vendor_id);
01138                 dpos += 4;
01139                 dlen -= 4;
01140         }
01141 
01142         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: AVP data", dpos, dlen);
01143 
01144         if (vendor_id == 0 && avp_code == RADIUS_ATTR_EAP_MESSAGE) {
01145                 if (eap_ttls_parse_attr_eap(dpos, dlen, parse) < 0)
01146                         return -1;
01147         } else if (vendor_id == 0 && avp_code == RADIUS_ATTR_REPLY_MESSAGE) {
01148                 /* This is an optional message that can be displayed to
01149                  * the user. */
01150                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: AVP - Reply-Message",
01151                                   dpos, dlen);
01152         } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
01153                    avp_code == RADIUS_ATTR_MS_CHAP2_SUCCESS) {
01154                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP2-Success",
01155                                   dpos, dlen);
01156                 if (dlen != 43) {
01157                         wpa_printf(MSG_WARNING, "EAP-TTLS: Unexpected "
01158                                    "MS-CHAP2-Success length "
01159                                    "(len=%lu, expected 43)",
01160                                    (unsigned long) dlen);
01161                         return -1;
01162                 }
01163                 parse->mschapv2 = dpos;
01164         } else if (vendor_id == RADIUS_VENDOR_ID_MICROSOFT &&
01165                    avp_code == RADIUS_ATTR_MS_CHAP_ERROR) {
01166                 wpa_hexdump_ascii(MSG_DEBUG, "EAP-TTLS: MS-CHAP-Error",
01167                                   dpos, dlen);
01168                 parse->mschapv2_error = 1;
01169         } else if (avp_flags & AVP_FLAGS_MANDATORY) {
01170                 wpa_printf(MSG_WARNING, "EAP-TTLS: Unsupported mandatory AVP "
01171                            "code %d vendor_id %d - dropped",
01172                            (int) avp_code, (int) vendor_id);
01173                 return -1;
01174         } else {
01175                 wpa_printf(MSG_DEBUG, "EAP-TTLS: Ignoring unsupported AVP "
01176                            "code %d vendor_id %d",
01177                            (int) avp_code, (int) vendor_id);
01178         }
01179 
01180         return avp_length;
01181 }
01182 
01183 
01184 static int eap_ttls_parse_avps(struct wpabuf *in_decrypted,
01185                                struct ttls_parse_avp *parse)
01186 {
01187         u8 *pos;
01188         size_t left, pad;
01189         int avp_length;
01190 
01191         pos = wpabuf_mhead(in_decrypted);
01192         left = wpabuf_len(in_decrypted);
01193         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Decrypted Phase 2 AVPs", pos, left);
01194         if (left < sizeof(struct ttls_avp)) {
01195                 wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 AVP frame"
01196                            " len=%lu expected %lu or more - dropped",
01197                            (unsigned long) left,
01198                            (unsigned long) sizeof(struct ttls_avp));
01199                 return -1;
01200         }
01201 
01202         /* Parse AVPs */
01203         os_memset(parse, 0, sizeof(*parse));
01204 
01205         while (left > 0) {
01206                 avp_length = eap_ttls_parse_avp(pos, left, parse);
01207                 if (avp_length < 0)
01208                         return -1;
01209 
01210                 pad = (4 - (avp_length & 3)) & 3;
01211                 pos += avp_length + pad;
01212                 if (left < avp_length + pad)
01213                         left = 0;
01214                 else
01215                         left -= avp_length + pad;
01216         }
01217 
01218         return 0;
01219 }
01220 
01221 
01222 static u8 * eap_ttls_fake_identity_request(void)
01223 {
01224         struct eap_hdr *hdr;
01225         u8 *buf;
01226 
01227         wpa_printf(MSG_DEBUG, "EAP-TTLS: empty data in beginning of "
01228                    "Phase 2 - use fake EAP-Request Identity");
01229         buf = os_malloc(sizeof(*hdr) + 1);
01230         if (buf == NULL) {
01231                 wpa_printf(MSG_WARNING, "EAP-TTLS: failed to allocate "
01232                            "memory for fake EAP-Identity Request");
01233                 return NULL;
01234         }
01235 
01236         hdr = (struct eap_hdr *) buf;
01237         hdr->code = EAP_CODE_REQUEST;
01238         hdr->identifier = 0;
01239         hdr->length = host_to_be16(sizeof(*hdr) + 1);
01240         buf[sizeof(*hdr)] = EAP_TYPE_IDENTITY;
01241 
01242         return buf;
01243 }
01244 
01245 
01246 static int eap_ttls_encrypt_response(struct eap_sm *sm,
01247                                      struct eap_ttls_data *data,
01248                                      struct wpabuf *resp, u8 identifier,
01249                                      struct wpabuf **out_data)
01250 {
01251         if (resp == NULL)
01252                 return 0;
01253 
01254         wpa_hexdump_buf_key(MSG_DEBUG, "EAP-TTLS: Encrypting Phase 2 data",
01255                             resp);
01256         if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS,
01257                                  data->ttls_version, identifier,
01258                                  resp, out_data)) {
01259                 wpa_printf(MSG_INFO, "EAP-TTLS: Failed to encrypt a Phase 2 "
01260                            "frame");
01261                 return -1;
01262         }
01263         wpabuf_free(resp);
01264 
01265         return 0;
01266 }
01267 
01268 
01269 static int eap_ttls_process_phase2_eap(struct eap_sm *sm,
01270                                        struct eap_ttls_data *data,
01271                                        struct eap_method_ret *ret,
01272                                        struct ttls_parse_avp *parse,
01273                                        struct wpabuf **resp)
01274 {
01275         struct eap_hdr *hdr;
01276         size_t len;
01277 
01278         if (parse->eapdata == NULL) {
01279                 wpa_printf(MSG_WARNING, "EAP-TTLS: No EAP Message in the "
01280                            "packet - dropped");
01281                 return -1;
01282         }
01283 
01284         wpa_hexdump(MSG_DEBUG, "EAP-TTLS: Phase 2 EAP",
01285                     parse->eapdata, parse->eap_len);
01286         hdr = (struct eap_hdr *) parse->eapdata;
01287 
01288         if (parse->eap_len < sizeof(*hdr)) {
01289                 wpa_printf(MSG_WARNING, "EAP-TTLS: Too short Phase 2 EAP "
01290                            "frame (len=%lu, expected %lu or more) - dropped",
01291                            (unsigned long) parse->eap_len,
01292                            (unsigned long) sizeof(*hdr));
01293                 return -1;
01294         }
01295         len = be_to_host16(hdr->length);
01296         if (len > parse->eap_len) {
01297                 wpa_printf(MSG_INFO, "EAP-TTLS: Length mismatch in Phase 2 "
01298                            "EAP frame (EAP hdr len=%lu, EAP data len in "
01299                            "AVP=%lu)",
01300                            (unsigned long) len,
01301                            (unsigned long) parse->eap_len);
01302                 return -1;
01303         }
01304         wpa_printf(MSG_DEBUG, "EAP-TTLS: received Phase 2: code=%d "
01305                    "identifier=%d length=%lu",
01306                    hdr->code, hdr->identifier, (unsigned long) len);
01307         switch (hdr->code) {
01308         case EAP_CODE_REQUEST:
01309                 if (eap_ttls_phase2_request(sm, data, ret, hdr, resp)) {
01310                         wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request "
01311                                    "processing failed");
01312                         return -1;
01313                 }
01314                 break;
01315         default:
01316                 wpa_printf(MSG_INFO, "EAP-TTLS: Unexpected code=%d in "
01317                            "Phase 2 EAP header", hdr->code);
01318                 return -1;
01319         }
01320 
01321         return 0;
01322 }
01323 
01324 
01325 static int eap_ttls_process_phase2_mschapv2(struct eap_sm *sm,
01326                                             struct eap_ttls_data *data,
01327                                             struct eap_method_ret *ret,
01328                                             struct ttls_parse_avp *parse)
01329 {
01330         if (parse->mschapv2_error) {
01331                 wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAPV2: Received "
01332                            "MS-CHAP-Error - failed");
01333                 ret->methodState = METHOD_DONE;
01334                 ret->decision = DECISION_FAIL;
01335                 /* Reply with empty data to ACK error */
01336                 return 1;
01337         }
01338 
01339         if (parse->mschapv2 == NULL) {
01340 #ifdef EAP_TNC
01341                 if (data->phase2_success && parse->eapdata) {
01342                         /*
01343                          * Allow EAP-TNC to be started after successfully
01344                          * completed MSCHAPV2.
01345                          */
01346                         return 1;
01347                 }
01348 #endif /* EAP_TNC */
01349                 wpa_printf(MSG_WARNING, "EAP-TTLS: no MS-CHAP2-Success AVP "
01350                            "received for Phase2 MSCHAPV2");
01351                 return -1;
01352         }
01353         if (parse->mschapv2[0] != data->ident) {
01354                 wpa_printf(MSG_WARNING, "EAP-TTLS: Ident mismatch for Phase 2 "
01355                            "MSCHAPV2 (received Ident 0x%02x, expected 0x%02x)",
01356                            parse->mschapv2[0], data->ident);
01357                 return -1;
01358         }
01359         if (!data->auth_response_valid ||
01360             mschapv2_verify_auth_response(data->auth_response,
01361                                           parse->mschapv2 + 1, 42)) {
01362                 wpa_printf(MSG_WARNING, "EAP-TTLS: Invalid authenticator "
01363                            "response in Phase 2 MSCHAPV2 success request");
01364                 return -1;
01365         }
01366 
01367         wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 MSCHAPV2 "
01368                    "authentication succeeded");
01369         if (data->ttls_version > 0) {
01370                 /*
01371                  * EAP-TTLSv1 uses TLS/IA FinalPhaseFinished to report
01372                  * success, so do not allow connection to be terminated
01373                  * yet.
01374                  */
01375                 ret->methodState = METHOD_CONT;
01376                 ret->decision = DECISION_COND_SUCC;
01377         } else {
01378                 ret->methodState = METHOD_DONE;
01379                 ret->decision = DECISION_UNCOND_SUCC;
01380                 data->phase2_success = 1;
01381         }
01382 
01383         /*
01384          * Reply with empty data; authentication server will reply
01385          * with EAP-Success after this.
01386          */
01387         return 1;
01388 }
01389 
01390 
01391 #ifdef EAP_TNC
01392 static int eap_ttls_process_tnc_start(struct eap_sm *sm,
01393                                       struct eap_ttls_data *data,
01394                                       struct eap_method_ret *ret,
01395                                       struct ttls_parse_avp *parse,
01396                                       struct wpabuf **resp)
01397 {
01398         /* TNC uses inner EAP method after non-EAP TTLS phase 2. */
01399         if (parse->eapdata == NULL) {
01400                 wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received "
01401                            "unexpected tunneled data (no EAP)");
01402                 return -1;
01403         }
01404 
01405         if (!data->ready_for_tnc) {
01406                 wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received "
01407                            "EAP after non-EAP, but not ready for TNC");
01408                 return -1;
01409         }
01410 
01411         wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed "
01412                    "non-EAP method");
01413         data->tnc_started = 1;
01414 
01415         if (eap_ttls_process_phase2_eap(sm, data, ret, parse, resp) < 0)
01416                 return -1;
01417 
01418         return 0;
01419 }
01420 #endif /* EAP_TNC */
01421 
01422 
01423 static int eap_ttls_process_decrypted(struct eap_sm *sm,
01424                                       struct eap_ttls_data *data,
01425                                       struct eap_method_ret *ret,
01426                                       u8 identifier,
01427                                       struct ttls_parse_avp *parse,
01428                                       struct wpabuf *in_decrypted,
01429                                       struct wpabuf **out_data)
01430 {
01431         struct wpabuf *resp = NULL;
01432         struct eap_peer_config *config = eap_get_config(sm);
01433         int res;
01434         enum phase2_types phase2_type = data->phase2_type;
01435 
01436 #ifdef EAP_TNC
01437         if (data->tnc_started)
01438                 phase2_type = EAP_TTLS_PHASE2_EAP;
01439 #endif /* EAP_TNC */
01440 
01441         switch (phase2_type) {
01442         case EAP_TTLS_PHASE2_EAP:
01443                 if (eap_ttls_process_phase2_eap(sm, data, ret, parse, &resp) <
01444                     0)
01445                         return -1;
01446                 break;
01447         case EAP_TTLS_PHASE2_MSCHAPV2:
01448                 res = eap_ttls_process_phase2_mschapv2(sm, data, ret, parse);
01449 #ifdef EAP_TNC
01450                 if (res == 1 && parse->eapdata && data->phase2_success) {
01451                         /*
01452                          * TNC may be required as the next
01453                          * authentication method within the tunnel.
01454                          */
01455                         ret->methodState = METHOD_MAY_CONT;
01456                         data->ready_for_tnc = 1;
01457                         if (eap_ttls_process_tnc_start(sm, data, ret, parse,
01458                                                        &resp) == 0)
01459                                 break;
01460                 }
01461 #endif /* EAP_TNC */
01462                 return res;
01463         case EAP_TTLS_PHASE2_MSCHAP:
01464         case EAP_TTLS_PHASE2_PAP:
01465         case EAP_TTLS_PHASE2_CHAP:
01466 #ifdef EAP_TNC
01467                 if (eap_ttls_process_tnc_start(sm, data, ret, parse, &resp) <
01468                     0)
01469                         return -1;
01470                 break;
01471 #else /* EAP_TNC */
01472                 /* EAP-TTLS/{MSCHAP,PAP,CHAP} should not send any TLS tunneled
01473                  * requests to the supplicant */
01474                 wpa_printf(MSG_INFO, "EAP-TTLS: Phase 2 received unexpected "
01475                            "tunneled data");
01476                 return -1;
01477 #endif /* EAP_TNC */
01478         }
01479 
01480         if (resp) {
01481                 if (eap_ttls_encrypt_response(sm, data, resp, identifier,
01482                                               out_data) < 0)
01483                         return -1;
01484         } else if (config->pending_req_identity ||
01485                    config->pending_req_password ||
01486                    config->pending_req_otp ||
01487                    config->pending_req_new_password) {
01488                 wpabuf_free(data->pending_phase2_req);
01489                 data->pending_phase2_req = wpabuf_dup(in_decrypted);
01490         }
01491 
01492         return 0;
01493 }
01494 
01495 
01496 #if EAP_TTLS_VERSION > 0
01497 static void eap_ttls_final_phase_finished(struct eap_sm *sm,
01498                                           struct eap_ttls_data *data,
01499                                           struct eap_method_ret *ret,
01500                                           u8 identifier,
01501                                           struct wpabuf **out_data)
01502 {
01503         wpa_printf(MSG_DEBUG, "EAP-TTLS: FinalPhaseFinished received");
01504         wpa_printf(MSG_INFO, "EAP-TTLS: TLS/IA authentication succeeded");
01505         ret->methodState = METHOD_DONE;
01506         ret->decision = DECISION_UNCOND_SUCC;
01507         data->phase2_success = 1;
01508         *out_data = eap_ttls_build_phase_finished(sm, data, identifier, 1);
01509         eap_ttls_v1_derive_key(sm, data);
01510 }
01511 #endif /* EAP_TTLS_VERSION */
01512 
01513 
01514 static int eap_ttls_implicit_identity_request(struct eap_sm *sm,
01515                                               struct eap_ttls_data *data,
01516                                               struct eap_method_ret *ret,
01517                                               u8 identifier,
01518                                               struct wpabuf **out_data)
01519 {
01520         int retval = 0;
01521         struct eap_hdr *hdr;
01522         struct wpabuf *resp;
01523 
01524         hdr = (struct eap_hdr *) eap_ttls_fake_identity_request();
01525         if (hdr == NULL) {
01526                 ret->methodState = METHOD_DONE;
01527                 ret->decision = DECISION_FAIL;
01528                 return -1;
01529         }
01530 
01531         resp = NULL;
01532         if (eap_ttls_phase2_request(sm, data, ret, hdr, &resp)) {
01533                 wpa_printf(MSG_INFO, "EAP-TTLS: Phase2 Request "
01534                            "processing failed");
01535                 retval = -1;
01536         } else {
01537                 retval = eap_ttls_encrypt_response(sm, data, resp, identifier,
01538                                                    out_data);
01539         }
01540 
01541         os_free(hdr);
01542 
01543         if (retval < 0) {
01544                 ret->methodState = METHOD_DONE;
01545                 ret->decision = DECISION_FAIL;
01546         }
01547 
01548         return retval;
01549 }
01550 
01551 
01552 static int eap_ttls_phase2_start(struct eap_sm *sm, struct eap_ttls_data *data,
01553                                  struct eap_method_ret *ret, u8 identifier,
01554                                  struct wpabuf **out_data)
01555 {
01556         data->phase2_start = 0;
01557 
01558         /*
01559          * EAP-TTLS does not use Phase2 on fast re-auth; this must be done only
01560          * if TLS part was indeed resuming a previous session. Most
01561          * Authentication Servers terminate EAP-TTLS before reaching this
01562          * point, but some do not. Make wpa_supplicant stop phase 2 here, if
01563          * needed.
01564          */
01565         if (data->reauth &&
01566             tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
01567                 wpa_printf(MSG_DEBUG, "EAP-TTLS: Session resumption - "
01568                            "skip phase 2");
01569                 *out_data = eap_peer_tls_build_ack(identifier, EAP_TYPE_TTLS,
01570                                                    data->ttls_version);
01571                 ret->methodState = METHOD_DONE;
01572                 ret->decision = DECISION_UNCOND_SUCC;
01573                 data->phase2_success = 1;
01574                 return 0;
01575         }
01576 
01577         return eap_ttls_implicit_identity_request(sm, data, ret, identifier,
01578                                                   out_data);
01579 }
01580 
01581 
01582 static int eap_ttls_decrypt(struct eap_sm *sm, struct eap_ttls_data *data,
01583                             struct eap_method_ret *ret, u8 identifier,
01584                             const struct wpabuf *in_data,
01585                             struct wpabuf **out_data)
01586 {
01587         struct wpabuf *in_decrypted = NULL;
01588         int retval = 0;
01589         struct ttls_parse_avp parse;
01590 
01591         os_memset(&parse, 0, sizeof(parse));
01592 
01593         wpa_printf(MSG_DEBUG, "EAP-TTLS: received %lu bytes encrypted data for"
01594                    " Phase 2",
01595                    in_data ? (unsigned long) wpabuf_len(in_data) : 0);
01596 
01597         if (data->pending_phase2_req) {
01598                 wpa_printf(MSG_DEBUG, "EAP-TTLS: Pending Phase 2 request - "
01599                            "skip decryption and use old data");
01600                 /* Clear TLS reassembly state. */
01601                 eap_peer_tls_reset_input(&data->ssl);
01602 
01603                 in_decrypted = data->pending_phase2_req;
01604                 data->pending_phase2_req = NULL;
01605                 if (wpabuf_len(in_decrypted) == 0) {
01606                         wpabuf_free(in_decrypted);
01607                         return eap_ttls_implicit_identity_request(
01608                                 sm, data, ret, identifier, out_data);
01609                 }
01610                 goto continue_req;
01611         }
01612 
01613         if ((in_data == NULL || wpabuf_len(in_data) == 0) &&
01614             data->phase2_start) {
01615                 return eap_ttls_phase2_start(sm, data, ret, identifier,
01616                                              out_data);
01617         }
01618 
01619         if (in_data == NULL || wpabuf_len(in_data) == 0) {
01620                 /* Received TLS ACK - requesting more fragments */
01621                 return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_TTLS,
01622                                             data->ttls_version,
01623                                             identifier, NULL, out_data);
01624         }
01625 
01626         retval = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
01627         if (retval)
01628                 goto done;
01629 
01630 #if EAP_TTLS_VERSION > 0
01631         if (data->ttls_version > 0 &&
01632             (in_decrypted == NULL || wpabuf_len(in_decrypted) == 0) &&
01633             tls_connection_ia_final_phase_finished(sm->ssl_ctx,
01634                                                    data->ssl.conn)) {
01635                 eap_ttls_final_phase_finished(sm, data, ret, identifier,
01636                                               out_data);
01637                 goto done;
01638         }
01639 #endif /* EAP_TTLS_VERSION */
01640 
01641 continue_req:
01642         data->phase2_start = 0;
01643 
01644         if (eap_ttls_parse_avps(in_decrypted, &parse) < 0) {
01645                 retval = -1;
01646                 goto done;
01647         }
01648 
01649         retval = eap_ttls_process_decrypted(sm, data, ret, identifier,
01650                                             &parse, in_decrypted, out_data);
01651 
01652 done:
01653         wpabuf_free(in_decrypted);
01654         os_free(parse.eapdata);
01655 
01656         if (retval < 0) {
01657                 ret->methodState = METHOD_DONE;
01658                 ret->decision = DECISION_FAIL;
01659         }
01660 
01661         return retval;
01662 }
01663 
01664 
01665 static int eap_ttls_process_start(struct eap_sm *sm,
01666                                   struct eap_ttls_data *data, u8 flags,
01667                                   struct eap_method_ret *ret)
01668 {
01669         struct eap_peer_config *config = eap_get_config(sm);
01670 
01671         wpa_printf(MSG_DEBUG, "EAP-TTLS: Start (server ver=%d, own ver=%d)",
01672                    flags & EAP_TLS_VERSION_MASK, data->ttls_version);
01673 #if EAP_TTLS_VERSION > 0
01674         if ((flags & EAP_TLS_VERSION_MASK) < data->ttls_version)
01675                 data->ttls_version = flags & EAP_TLS_VERSION_MASK;
01676         if (data->force_ttls_version >= 0 &&
01677             data->force_ttls_version != data->ttls_version) {
01678                 wpa_printf(MSG_WARNING, "EAP-TTLS: Failed to select "
01679                            "forced TTLS version %d",
01680                            data->force_ttls_version);
01681                 ret->methodState = METHOD_DONE;
01682                 ret->decision = DECISION_FAIL;
01683                 ret->allowNotifications = FALSE;
01684                 return -1;
01685         }
01686         wpa_printf(MSG_DEBUG, "EAP-TTLS: Using TTLS version %d",
01687                    data->ttls_version);
01688 
01689         if (data->ttls_version > 0)
01690                 data->ssl.tls_ia = 1;
01691 #endif /* EAP_TTLS_VERSION */
01692         if (!data->ssl_initialized &&
01693             eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
01694                 wpa_printf(MSG_INFO, "EAP-TTLS: Failed to initialize SSL.");
01695                 return -1;
01696         }
01697         data->ssl_initialized = 1;
01698 
01699         wpa_printf(MSG_DEBUG, "EAP-TTLS: Start");
01700 
01701         return 0;
01702 }
01703 
01704 
01705 static int eap_ttls_process_handshake(struct eap_sm *sm,
01706                                       struct eap_ttls_data *data,
01707                                       struct eap_method_ret *ret,
01708                                       u8 identifier,
01709                                       const u8 *in_data, size_t in_len,
01710                                       struct wpabuf **out_data)
01711 {
01712         int res;
01713 
01714         res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TTLS,
01715                                           data->ttls_version, identifier,
01716                                           in_data, in_len, out_data);
01717 
01718         if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
01719                 wpa_printf(MSG_DEBUG, "EAP-TTLS: TLS done, proceed to "
01720                            "Phase 2");
01721                 if (data->resuming) {
01722                         wpa_printf(MSG_DEBUG, "EAP-TTLS: fast reauth - may "
01723                                    "skip Phase 2");
01724                         ret->decision = DECISION_COND_SUCC;
01725                         ret->methodState = METHOD_MAY_CONT;
01726                 }
01727                 data->phase2_start = 1;
01728                 if (data->ttls_version == 0)
01729                         eap_ttls_v0_derive_key(sm, data);
01730 
01731                 if (*out_data == NULL || wpabuf_len(*out_data) == 0) {
01732                         if (eap_ttls_decrypt(sm, data, ret, identifier,
01733                                              NULL, out_data)) {
01734                                 wpa_printf(MSG_WARNING, "EAP-TTLS: "
01735                                            "failed to process early "
01736                                            "start for Phase 2");
01737                         }
01738                         res = 0;
01739                 }
01740                 data->resuming = 0;
01741         }
01742 
01743         if (res == 2) {
01744                 struct wpabuf msg;
01745                 /*
01746                  * Application data included in the handshake message.
01747                  */
01748                 wpabuf_free(data->pending_phase2_req);
01749                 data->pending_phase2_req = *out_data;
01750                 *out_data = NULL;
01751                 wpabuf_set(&msg, in_data, in_len);
01752                 res = eap_ttls_decrypt(sm, data, ret, identifier, &msg,
01753                                        out_data);
01754         }
01755 
01756         return res;
01757 }
01758 
01759 
01760 static void eap_ttls_check_auth_status(struct eap_sm *sm, 
01761                                        struct eap_ttls_data *data,
01762                                        struct eap_method_ret *ret)
01763 {
01764         if (data->ttls_version == 0 && ret->methodState == METHOD_DONE) {
01765                 ret->allowNotifications = FALSE;
01766                 if (ret->decision == DECISION_UNCOND_SUCC ||
01767                     ret->decision == DECISION_COND_SUCC) {
01768                         wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
01769                                    "completed successfully");
01770                         data->phase2_success = 1;
01771 #ifdef EAP_TNC
01772                         if (!data->ready_for_tnc && !data->tnc_started) {
01773                                 /*
01774                                  * TNC may be required as the next
01775                                  * authentication method within the tunnel.
01776                                  */
01777                                 ret->methodState = METHOD_MAY_CONT;
01778                                 data->ready_for_tnc = 1;
01779                         }
01780 #endif /* EAP_TNC */
01781                 }
01782         } else if (data->ttls_version == 0 &&
01783                    ret->methodState == METHOD_MAY_CONT &&
01784                    (ret->decision == DECISION_UNCOND_SUCC ||
01785                     ret->decision == DECISION_COND_SUCC)) {
01786                         wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication "
01787                                    "completed successfully (MAY_CONT)");
01788                         data->phase2_success = 1;
01789         }
01790 }
01791 
01792 
01793 static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv,
01794                                         struct eap_method_ret *ret,
01795                                         const struct wpabuf *reqData)
01796 {
01797         size_t left;
01798         int res;
01799         u8 flags, id;
01800         struct wpabuf *resp;
01801         const u8 *pos;
01802         struct eap_ttls_data *data = priv;
01803 
01804         pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TTLS, ret,
01805                                         reqData, &left, &flags);
01806         if (pos == NULL)
01807                 return NULL;
01808         id = eap_get_id(reqData);
01809 
01810         if (flags & EAP_TLS_FLAGS_START) {
01811                 if (eap_ttls_process_start(sm, data, flags, ret) < 0)
01812                         return NULL;
01813 
01814                 /* RFC 5281, Ch. 9.2:
01815                  * "This packet MAY contain additional information in the form
01816                  * of AVPs, which may provide useful hints to the client"
01817                  * For now, ignore any potential extra data.
01818                  */
01819                 left = 0;
01820         } else if (!data->ssl_initialized) {
01821                 wpa_printf(MSG_DEBUG, "EAP-TTLS: First message did not "
01822                            "include Start flag");
01823                 ret->methodState = METHOD_DONE;
01824                 ret->decision = DECISION_FAIL;
01825                 ret->allowNotifications = FALSE;
01826                 return NULL;
01827         }
01828 
01829         resp = NULL;
01830         if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
01831             !data->resuming) {
01832                 struct wpabuf msg;
01833                 wpabuf_set(&msg, pos, left);
01834                 res = eap_ttls_decrypt(sm, data, ret, id, &msg, &resp);
01835         } else {
01836                 res = eap_ttls_process_handshake(sm, data, ret, id,
01837                                                  pos, left, &resp);
01838         }
01839 
01840         eap_ttls_check_auth_status(sm, data, ret);
01841 
01842         /* FIX: what about res == -1? Could just move all error processing into
01843          * the other functions and get rid of this res==1 case here. */
01844         if (res == 1) {
01845                 wpabuf_free(resp);
01846                 return eap_peer_tls_build_ack(id, EAP_TYPE_TTLS,
01847                                               data->ttls_version);
01848         }
01849         return resp;
01850 }
01851 
01852 
01853 static Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv)
01854 {
01855         struct eap_ttls_data *data = priv;
01856         return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
01857                 data->phase2_success;
01858 }
01859 
01860 
01861 static void eap_ttls_deinit_for_reauth(struct eap_sm *sm, void *priv)
01862 {
01863         struct eap_ttls_data *data = priv;
01864         wpabuf_free(data->pending_phase2_req);
01865         data->pending_phase2_req = NULL;
01866 #ifdef EAP_TNC
01867         data->ready_for_tnc = 0;
01868         data->tnc_started = 0;
01869 #endif /* EAP_TNC */
01870 }
01871 
01872 
01873 static void * eap_ttls_init_for_reauth(struct eap_sm *sm, void *priv)
01874 {
01875         struct eap_ttls_data *data = priv;
01876         os_free(data->key_data);
01877         data->key_data = NULL;
01878         if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
01879                 os_free(data);
01880                 return NULL;
01881         }
01882         if (data->phase2_priv && data->phase2_method &&
01883             data->phase2_method->init_for_reauth)
01884                 data->phase2_method->init_for_reauth(sm, data->phase2_priv);
01885         data->phase2_start = 0;
01886         data->phase2_success = 0;
01887         data->resuming = 1;
01888         data->reauth = 1;
01889         return priv;
01890 }
01891 
01892 
01893 static int eap_ttls_get_status(struct eap_sm *sm, void *priv, char *buf,
01894                                size_t buflen, int verbose)
01895 {
01896         struct eap_ttls_data *data = priv;
01897         int len, ret;
01898 
01899         len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
01900         ret = os_snprintf(buf + len, buflen - len,
01901                           "EAP-TTLSv%d Phase2 method=",
01902                           data->ttls_version);
01903         if (ret < 0 || (size_t) ret >= buflen - len)
01904                 return len;
01905         len += ret;
01906         switch (data->phase2_type) {
01907         case EAP_TTLS_PHASE2_EAP:
01908                 ret = os_snprintf(buf + len, buflen - len, "EAP-%s\n",
01909                                   data->phase2_method ?
01910                                   data->phase2_method->name : "?");
01911                 break;
01912         case EAP_TTLS_PHASE2_MSCHAPV2:
01913                 ret = os_snprintf(buf + len, buflen - len, "MSCHAPV2\n");
01914                 break;
01915         case EAP_TTLS_PHASE2_MSCHAP:
01916                 ret = os_snprintf(buf + len, buflen - len, "MSCHAP\n");
01917                 break;
01918         case EAP_TTLS_PHASE2_PAP:
01919                 ret = os_snprintf(buf + len, buflen - len, "PAP\n");
01920                 break;
01921         case EAP_TTLS_PHASE2_CHAP:
01922                 ret = os_snprintf(buf + len, buflen - len, "CHAP\n");
01923                 break;
01924         default:
01925                 ret = 0;
01926                 break;
01927         }
01928         if (ret < 0 || (size_t) ret >= buflen - len)
01929                 return len;
01930         len += ret;
01931 
01932         return len;
01933 }
01934 
01935 
01936 static Boolean eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv)
01937 {
01938         struct eap_ttls_data *data = priv;
01939         return data->key_data != NULL && data->phase2_success;
01940 }
01941 
01942 
01943 static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
01944 {
01945         struct eap_ttls_data *data = priv;
01946         u8 *key;
01947 
01948         if (data->key_data == NULL || !data->phase2_success)
01949                 return NULL;
01950 
01951         key = os_malloc(EAP_TLS_KEY_LEN);
01952         if (key == NULL)
01953                 return NULL;
01954 
01955         *len = EAP_TLS_KEY_LEN;
01956         os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
01957 
01958         return key;
01959 }
01960 
01961 
01962 int eap_peer_ttls_register(void)
01963 {
01964         struct eap_method *eap;
01965         int ret;
01966 
01967         eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
01968                                     EAP_VENDOR_IETF, EAP_TYPE_TTLS, "TTLS");
01969         if (eap == NULL)
01970                 return -1;
01971 
01972         eap->init = eap_ttls_init;
01973         eap->deinit = eap_ttls_deinit;
01974         eap->process = eap_ttls_process;
01975         eap->isKeyAvailable = eap_ttls_isKeyAvailable;
01976         eap->getKey = eap_ttls_getKey;
01977         eap->get_status = eap_ttls_get_status;
01978         eap->has_reauth_data = eap_ttls_has_reauth_data;
01979         eap->deinit_for_reauth = eap_ttls_deinit_for_reauth;
01980         eap->init_for_reauth = eap_ttls_init_for_reauth;
01981 
01982         ret = eap_peer_method_register(eap);
01983         if (ret)
01984                 eap_peer_method_free(eap);
01985         return ret;
01986 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:26:37