Merge branch 'vendor/GCC50'
[dragonfly.git] / contrib / hostapd / src / eap_peer / eap_otp.c
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         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 }