1*6d49e1aeSJan Lentfer /* 2*6d49e1aeSJan Lentfer * EAP peer method: EAP-GTC (RFC 3748) 3*6d49e1aeSJan Lentfer * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> 4*6d49e1aeSJan Lentfer * 5*6d49e1aeSJan Lentfer * This program is free software; you can redistribute it and/or modify 6*6d49e1aeSJan Lentfer * it under the terms of the GNU General Public License version 2 as 7*6d49e1aeSJan Lentfer * published by the Free Software Foundation. 8*6d49e1aeSJan Lentfer * 9*6d49e1aeSJan Lentfer * Alternatively, this software may be distributed under the terms of BSD 10*6d49e1aeSJan Lentfer * license. 11*6d49e1aeSJan Lentfer * 12*6d49e1aeSJan Lentfer * See README and COPYING for more details. 13*6d49e1aeSJan Lentfer */ 14*6d49e1aeSJan Lentfer 15*6d49e1aeSJan Lentfer #include "includes.h" 16*6d49e1aeSJan Lentfer 17*6d49e1aeSJan Lentfer #include "common.h" 18*6d49e1aeSJan Lentfer #include "eap_i.h" 19*6d49e1aeSJan Lentfer 20*6d49e1aeSJan Lentfer 21*6d49e1aeSJan Lentfer struct eap_gtc_data { 22*6d49e1aeSJan Lentfer int prefix; 23*6d49e1aeSJan Lentfer }; 24*6d49e1aeSJan Lentfer 25*6d49e1aeSJan Lentfer 26*6d49e1aeSJan Lentfer static void * eap_gtc_init(struct eap_sm *sm) 27*6d49e1aeSJan Lentfer { 28*6d49e1aeSJan Lentfer struct eap_gtc_data *data; 29*6d49e1aeSJan Lentfer data = os_zalloc(sizeof(*data)); 30*6d49e1aeSJan Lentfer if (data == NULL) 31*6d49e1aeSJan Lentfer return NULL; 32*6d49e1aeSJan Lentfer 33*6d49e1aeSJan Lentfer if (sm->m && sm->m->vendor == EAP_VENDOR_IETF && 34*6d49e1aeSJan Lentfer sm->m->method == EAP_TYPE_FAST) { 35*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix " 36*6d49e1aeSJan Lentfer "with challenge/response"); 37*6d49e1aeSJan Lentfer data->prefix = 1; 38*6d49e1aeSJan Lentfer } 39*6d49e1aeSJan Lentfer return data; 40*6d49e1aeSJan Lentfer } 41*6d49e1aeSJan Lentfer 42*6d49e1aeSJan Lentfer 43*6d49e1aeSJan Lentfer static void eap_gtc_deinit(struct eap_sm *sm, void *priv) 44*6d49e1aeSJan Lentfer { 45*6d49e1aeSJan Lentfer struct eap_gtc_data *data = priv; 46*6d49e1aeSJan Lentfer os_free(data); 47*6d49e1aeSJan Lentfer } 48*6d49e1aeSJan Lentfer 49*6d49e1aeSJan Lentfer 50*6d49e1aeSJan Lentfer static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv, 51*6d49e1aeSJan Lentfer struct eap_method_ret *ret, 52*6d49e1aeSJan Lentfer const struct wpabuf *reqData) 53*6d49e1aeSJan Lentfer { 54*6d49e1aeSJan Lentfer struct eap_gtc_data *data = priv; 55*6d49e1aeSJan Lentfer struct wpabuf *resp; 56*6d49e1aeSJan Lentfer const u8 *pos, *password, *identity; 57*6d49e1aeSJan Lentfer size_t password_len, identity_len, len, plen; 58*6d49e1aeSJan Lentfer int otp; 59*6d49e1aeSJan Lentfer u8 id; 60*6d49e1aeSJan Lentfer 61*6d49e1aeSJan Lentfer pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, reqData, &len); 62*6d49e1aeSJan Lentfer if (pos == NULL) { 63*6d49e1aeSJan Lentfer ret->ignore = TRUE; 64*6d49e1aeSJan Lentfer return NULL; 65*6d49e1aeSJan Lentfer } 66*6d49e1aeSJan Lentfer id = eap_get_id(reqData); 67*6d49e1aeSJan Lentfer 68*6d49e1aeSJan Lentfer wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len); 69*6d49e1aeSJan Lentfer if (data->prefix && 70*6d49e1aeSJan Lentfer (len < 10 || os_memcmp(pos, "CHALLENGE=", 10) != 0)) { 71*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with " 72*6d49e1aeSJan Lentfer "expected prefix"); 73*6d49e1aeSJan Lentfer 74*6d49e1aeSJan Lentfer /* Send an empty response in order to allow tunneled 75*6d49e1aeSJan Lentfer * acknowledgement of the failure. This will also cover the 76*6d49e1aeSJan Lentfer * error case which seems to use EAP-MSCHAPv2 like error 77*6d49e1aeSJan Lentfer * reporting with EAP-GTC inside EAP-FAST tunnel. */ 78*6d49e1aeSJan Lentfer resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, 79*6d49e1aeSJan Lentfer 0, EAP_CODE_RESPONSE, id); 80*6d49e1aeSJan Lentfer return resp; 81*6d49e1aeSJan Lentfer } 82*6d49e1aeSJan Lentfer 83*6d49e1aeSJan Lentfer password = eap_get_config_otp(sm, &password_len); 84*6d49e1aeSJan Lentfer if (password) 85*6d49e1aeSJan Lentfer otp = 1; 86*6d49e1aeSJan Lentfer else { 87*6d49e1aeSJan Lentfer password = eap_get_config_password(sm, &password_len); 88*6d49e1aeSJan Lentfer otp = 0; 89*6d49e1aeSJan Lentfer } 90*6d49e1aeSJan Lentfer 91*6d49e1aeSJan Lentfer if (password == NULL) { 92*6d49e1aeSJan Lentfer wpa_printf(MSG_INFO, "EAP-GTC: Password not configured"); 93*6d49e1aeSJan Lentfer eap_sm_request_otp(sm, (const char *) pos, len); 94*6d49e1aeSJan Lentfer ret->ignore = TRUE; 95*6d49e1aeSJan Lentfer return NULL; 96*6d49e1aeSJan Lentfer } 97*6d49e1aeSJan Lentfer 98*6d49e1aeSJan Lentfer ret->ignore = FALSE; 99*6d49e1aeSJan Lentfer 100*6d49e1aeSJan Lentfer ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE; 101*6d49e1aeSJan Lentfer ret->decision = DECISION_COND_SUCC; 102*6d49e1aeSJan Lentfer ret->allowNotifications = FALSE; 103*6d49e1aeSJan Lentfer 104*6d49e1aeSJan Lentfer plen = password_len; 105*6d49e1aeSJan Lentfer identity = eap_get_config_identity(sm, &identity_len); 106*6d49e1aeSJan Lentfer if (identity == NULL) 107*6d49e1aeSJan Lentfer return NULL; 108*6d49e1aeSJan Lentfer if (data->prefix) 109*6d49e1aeSJan Lentfer plen += 9 + identity_len + 1; 110*6d49e1aeSJan Lentfer resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, plen, 111*6d49e1aeSJan Lentfer EAP_CODE_RESPONSE, id); 112*6d49e1aeSJan Lentfer if (resp == NULL) 113*6d49e1aeSJan Lentfer return NULL; 114*6d49e1aeSJan Lentfer if (data->prefix) { 115*6d49e1aeSJan Lentfer wpabuf_put_data(resp, "RESPONSE=", 9); 116*6d49e1aeSJan Lentfer wpabuf_put_data(resp, identity, identity_len); 117*6d49e1aeSJan Lentfer wpabuf_put_u8(resp, '\0'); 118*6d49e1aeSJan Lentfer } 119*6d49e1aeSJan Lentfer wpabuf_put_data(resp, password, password_len); 120*6d49e1aeSJan Lentfer wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response", 121*6d49e1aeSJan Lentfer wpabuf_head_u8(resp) + sizeof(struct eap_hdr) + 122*6d49e1aeSJan Lentfer 1, plen); 123*6d49e1aeSJan Lentfer 124*6d49e1aeSJan Lentfer if (otp) { 125*6d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password"); 126*6d49e1aeSJan Lentfer eap_clear_config_otp(sm); 127*6d49e1aeSJan Lentfer } 128*6d49e1aeSJan Lentfer 129*6d49e1aeSJan Lentfer return resp; 130*6d49e1aeSJan Lentfer } 131*6d49e1aeSJan Lentfer 132*6d49e1aeSJan Lentfer 133*6d49e1aeSJan Lentfer int eap_peer_gtc_register(void) 134*6d49e1aeSJan Lentfer { 135*6d49e1aeSJan Lentfer struct eap_method *eap; 136*6d49e1aeSJan Lentfer int ret; 137*6d49e1aeSJan Lentfer 138*6d49e1aeSJan Lentfer eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 139*6d49e1aeSJan Lentfer EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC"); 140*6d49e1aeSJan Lentfer if (eap == NULL) 141*6d49e1aeSJan Lentfer return -1; 142*6d49e1aeSJan Lentfer 143*6d49e1aeSJan Lentfer eap->init = eap_gtc_init; 144*6d49e1aeSJan Lentfer eap->deinit = eap_gtc_deinit; 145*6d49e1aeSJan Lentfer eap->process = eap_gtc_process; 146*6d49e1aeSJan Lentfer 147*6d49e1aeSJan Lentfer ret = eap_peer_method_register(eap); 148*6d49e1aeSJan Lentfer if (ret) 149*6d49e1aeSJan Lentfer eap_peer_method_free(eap); 150*6d49e1aeSJan Lentfer return ret; 151*6d49e1aeSJan Lentfer } 152