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
15static 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
23static void eap_otp_deinit(struct eap_sm *sm, void *priv)
24{
25}
26
27
28static 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
83int eap_peer_otp_register(void)
84{
85	struct eap_method *eap;
86	int ret;
87
88	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
89				    EAP_VENDOR_IETF, EAP_TYPE_OTP, "OTP");
90	if (eap == NULL)
91		return -1;
92
93	eap->init = eap_otp_init;
94	eap->deinit = eap_otp_deinit;
95	eap->process = eap_otp_process;
96
97	ret = eap_peer_method_register(eap);
98	if (ret)
99		eap_peer_method_free(eap);
100	return ret;
101}
102