Import of WPA supplicant 0.4.9
[dragonfly.git] / contrib / wpa_supplicant-0.4.9 / eap_gtc.c
1 /*
2  * WPA Supplicant / EAP-GTC (RFC 2284)
3  * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.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 <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18
19 #include "common.h"
20 #include "eap_i.h"
21 #include "wpa_supplicant.h"
22 #include "config_ssid.h"
23
24
25 struct eap_gtc_data {
26         int prefix;
27 };
28
29
30 static void * eap_gtc_init(struct eap_sm *sm)
31 {
32         struct eap_gtc_data *data;
33         data = malloc(sizeof(*data));
34         if (data == NULL)
35                 return NULL;
36         memset(data, 0, sizeof(*data));
37
38         if (sm->m && sm->m->method == EAP_TYPE_FAST) {
39                 wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix "
40                            "with challenge/response");
41                 data->prefix = 1;
42         }
43         return data;
44 }
45
46
47 static void eap_gtc_deinit(struct eap_sm *sm, void *priv)
48 {
49         struct eap_gtc_data *data = priv;
50         free(data);
51 }
52
53
54 static u8 * eap_gtc_process(struct eap_sm *sm, void *priv,
55                             struct eap_method_ret *ret,
56                             const u8 *reqData, size_t reqDataLen,
57                             size_t *respDataLen)
58 {
59         struct eap_gtc_data *data = priv;
60         struct wpa_ssid *config = eap_get_config(sm);
61         const struct eap_hdr *req;
62         struct eap_hdr *resp;
63         const u8 *pos, *password;
64         u8 *rpos;
65         size_t password_len, len;
66
67         pos = eap_hdr_validate(EAP_TYPE_GTC, reqData, reqDataLen, &len);
68         if (pos == NULL) {
69                 ret->ignore = TRUE;
70                 return NULL;
71         }
72         req = (const struct eap_hdr *) reqData;
73
74         wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len);
75         if (data->prefix &&
76             (len < 10 || memcmp(pos, "CHALLENGE=", 10) != 0)) {
77                 wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with "
78                            "expected prefix");
79
80                 /* Send an empty response in order to allow tunneled
81                  * acknowledgement of the failure. This will also cover the
82                  * error case which seems to use EAP-MSCHAPv2 like error
83                  * reporting with EAP-GTC inside EAP-FAST tunnel. */
84                 *respDataLen = sizeof(struct eap_hdr) + 1;
85                 resp = malloc(*respDataLen);
86                 if (resp == NULL)
87                         return NULL;
88                 resp->code = EAP_CODE_RESPONSE;
89                 resp->identifier = req->identifier;
90                 resp->length = host_to_be16(*respDataLen);
91                 rpos = (u8 *) (resp + 1);
92                 *rpos++ = EAP_TYPE_GTC;
93                 return (u8 *) resp;
94         }
95
96         if (config == NULL ||
97             (config->password == NULL && config->otp == NULL)) {
98                 wpa_printf(MSG_INFO, "EAP-GTC: Password not configured");
99                 eap_sm_request_otp(sm, config, (const char *) pos, len);
100                 ret->ignore = TRUE;
101                 return NULL;
102         }
103
104         if (config->otp) {
105                 password = config->otp;
106                 password_len = config->otp_len;
107         } else {
108                 password = config->password;
109                 password_len = config->password_len;
110         }
111
112         ret->ignore = FALSE;
113
114         ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE;
115         ret->decision = DECISION_COND_SUCC;
116         ret->allowNotifications = FALSE;
117
118         *respDataLen = sizeof(struct eap_hdr) + 1 + password_len;
119         if (data->prefix) {
120                 *respDataLen += 9 + config->identity_len + 1;
121         }
122         resp = malloc(*respDataLen);
123         if (resp == NULL)
124                 return NULL;
125         resp->code = EAP_CODE_RESPONSE;
126         resp->identifier = req->identifier;
127         resp->length = host_to_be16(*respDataLen);
128         rpos = (u8 *) (resp + 1);
129         *rpos++ = EAP_TYPE_GTC;
130         if (data->prefix) {
131                 memcpy(rpos, "RESPONSE=", 9);
132                 rpos += 9;
133                 memcpy(rpos, config->identity, config->identity_len);
134                 rpos += config->identity_len;
135                 *rpos++ = '\0';
136         }
137         memcpy(rpos, password, password_len);
138         wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response",
139                               (u8 *) (resp + 1) + 1,
140                               *respDataLen - sizeof(struct eap_hdr) - 1);
141
142         if (config->otp) {
143                 wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password");
144                 memset(config->otp, 0, config->otp_len);
145                 free(config->otp);
146                 config->otp = NULL;
147                 config->otp_len = 0;
148         }
149
150         return (u8 *) resp;
151 }
152
153
154 const struct eap_method eap_method_gtc =
155 {
156         .method = EAP_TYPE_GTC,
157         .name = "GTC",
158         .init = eap_gtc_init,
159         .deinit = eap_gtc_deinit,
160         .process = eap_gtc_process,
161 };