1 /*
2  * EAP peer method: EAP-OTP (RFC 3748)
3  * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "common.h"
12 #include "eap_i.h"
13 
14 
15 static void * eap_otp_init(struct eap_sm *sm)
16 {
17 	/* No need for private data. However, must return non-NULL to indicate
18 	 * success. */
19 	return (void *) 1;
20 }
21 
22 
23 static void eap_otp_deinit(struct eap_sm *sm, void *priv)
24 {
25 }
26 
27 
28 static struct wpabuf * eap_otp_process(struct eap_sm *sm, void *priv,
29 				       struct eap_method_ret *ret,
30 				       const struct wpabuf *reqData)
31 {
32 	struct wpabuf *resp;
33 	const u8 *pos, *password;
34 	size_t password_len, len;
35 	int otp;
36 
37 	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_OTP, reqData, &len);
38 	if (pos == NULL) {
39 		ret->ignore = TRUE;
40 		return NULL;
41 	}
42 	wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-OTP: Request message",
43 			  pos, len);
44 
45 	password = eap_get_config_otp(sm, &password_len);
46 	if (password)
47 		otp = 1;
48 	else {
49 		password = eap_get_config_password(sm, &password_len);
50 		otp = 0;
51 	}
52 
53 	if (password == NULL) {
54 		wpa_printf(MSG_INFO, "EAP-OTP: Password not configured");
55 		eap_sm_request_otp(sm, (const char *) pos, len);
56 		ret->ignore = TRUE;
57 		return NULL;
58 	}
59 
60 	ret->ignore = FALSE;
61 
62 	ret->methodState = METHOD_DONE;
63 	ret->decision = DECISION_COND_SUCC;
64 	ret->allowNotifications = FALSE;
65 
66 	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_OTP, password_len,
67 			     EAP_CODE_RESPONSE, eap_get_id(reqData));
68 	if (resp == NULL)
69 		return NULL;
70 	wpabuf_put_data(resp, password, password_len);
71 	wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-OTP: Response",
72 			      password, password_len);
73 
74 	if (otp) {
75 		wpa_printf(MSG_DEBUG, "EAP-OTP: Forgetting used password");
76 		eap_clear_config_otp(sm);
77 	}
78 
79 	return resp;
80 }
81 
82 
83 int eap_peer_otp_register(void)
84 {
85 	struct eap_method *eap;
86 
87 	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
88 				    EAP_VENDOR_IETF, EAP_TYPE_OTP, "OTP");
89 	if (eap == NULL)
90 		return -1;
91 
92 	eap->init = eap_otp_init;
93 	eap->deinit = eap_otp_deinit;
94 	eap->process = eap_otp_process;
95 
96 	return eap_peer_method_register(eap);
97 }
98