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