1/*
2 * EAP peer method: EAP-OTP (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
21static void * eap_otp_init(struct eap_sm *sm)
22{
23	/* No need for private data. However, must return non-NULL to indicate
24	 * success. */
25	return (void *) 1;
26}
27
28
29static void eap_otp_deinit(struct eap_sm *sm, void *priv)
30{
31}
32
33
34static struct wpabuf * eap_otp_process(struct eap_sm *sm, void *priv,
35				       struct eap_method_ret *ret,
36				       const struct wpabuf *reqData)
37{
38	struct wpabuf *resp;
39	const u8 *pos, *password;
40	size_t password_len, len;
41	int otp;
42
43	pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_OTP, reqData, &len);
44	if (pos == NULL) {
45		ret->ignore = TRUE;
46		return NULL;
47	}
48	wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-OTP: Request message",
49			  pos, len);
50
51	password = eap_get_config_otp(sm, &password_len);
52	if (password)
53		otp = 1;
54	else {
55		password = eap_get_config_password(sm, &password_len);
56		otp = 0;
57	}
58
59	if (password == NULL) {
60		wpa_printf(MSG_INFO, "EAP-OTP: Password not configured");
61		eap_sm_request_otp(sm, (const char *) pos, len);
62		ret->ignore = TRUE;
63		return NULL;
64	}
65
66	ret->ignore = FALSE;
67
68	ret->methodState = METHOD_DONE;
69	ret->decision = DECISION_COND_SUCC;
70	ret->allowNotifications = FALSE;
71
72	resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_OTP, password_len,
73			     EAP_CODE_RESPONSE, eap_get_id(reqData));
74	if (resp == NULL)
75		return NULL;
76	wpabuf_put_data(resp, password, password_len);
77	wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-OTP: Response",
78			      password, password_len);
79
80	if (otp) {
81		wpa_printf(MSG_DEBUG, "EAP-OTP: Forgetting used password");
82		eap_clear_config_otp(sm);
83	}
84
85	return resp;
86}
87
88
89int eap_peer_otp_register(void)
90{
91	struct eap_method *eap;
92	int ret;
93
94	eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
95				    EAP_VENDOR_IETF, EAP_TYPE_OTP, "OTP");
96	if (eap == NULL)
97		return -1;
98
99	eap->init = eap_otp_init;
100	eap->deinit = eap_otp_deinit;
101	eap->process = eap_otp_process;
102
103	ret = eap_peer_method_register(eap);
104	if (ret)
105		eap_peer_method_free(eap);
106	return ret;
107}
108