~ubuntu-branches/ubuntu/hardy/wpasupplicant/hardy

« back to all changes in this revision

Viewing changes to src/eap_server/eap_tls.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * hostapd / EAP-TLS (RFC 2716)
3
 
 * Copyright (c) 2004-2007, 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
 
#include "eap_tls_common.h"
20
 
#include "tls.h"
21
 
 
22
 
 
23
 
static void eap_tls_reset(struct eap_sm *sm, void *priv);
24
 
 
25
 
 
26
 
struct eap_tls_data {
27
 
        struct eap_ssl_data ssl;
28
 
        enum { START, CONTINUE, SUCCESS, FAILURE } state;
29
 
};
30
 
 
31
 
 
32
 
static void * eap_tls_init(struct eap_sm *sm)
33
 
{
34
 
        struct eap_tls_data *data;
35
 
 
36
 
        data = os_zalloc(sizeof(*data));
37
 
        if (data == NULL)
38
 
                return NULL;
39
 
        data->state = START;
40
 
 
41
 
        if (eap_server_tls_ssl_init(sm, &data->ssl, 1)) {
42
 
                wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
43
 
                eap_tls_reset(sm, data);
44
 
                return NULL;
45
 
        }
46
 
 
47
 
        return data;
48
 
}
49
 
 
50
 
 
51
 
static void eap_tls_reset(struct eap_sm *sm, void *priv)
52
 
{
53
 
        struct eap_tls_data *data = priv;
54
 
        if (data == NULL)
55
 
                return;
56
 
        eap_server_tls_ssl_deinit(sm, &data->ssl);
57
 
        free(data);
58
 
}
59
 
 
60
 
 
61
 
static u8 * eap_tls_build_start(struct eap_sm *sm, struct eap_tls_data *data,
62
 
                                int id, size_t *reqDataLen)
63
 
{
64
 
        struct eap_hdr *req;
65
 
        u8 *pos;
66
 
 
67
 
        *reqDataLen = sizeof(*req) + 2;
68
 
        req = malloc(*reqDataLen);
69
 
        if (req == NULL) {
70
 
                wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for "
71
 
                           "request");
72
 
                data->state = FAILURE;
73
 
                return NULL;
74
 
        }
75
 
 
76
 
        req->code = EAP_CODE_REQUEST;
77
 
        req->identifier = id;
78
 
        req->length = host_to_be16(*reqDataLen);
79
 
        pos = (u8 *) (req + 1);
80
 
        *pos++ = EAP_TYPE_TLS;
81
 
        *pos = EAP_TLS_FLAGS_START;
82
 
 
83
 
        data->state = CONTINUE;
84
 
 
85
 
        return (u8 *) req;
86
 
}
87
 
 
88
 
 
89
 
static u8 * eap_tls_build_req(struct eap_sm *sm, struct eap_tls_data *data,
90
 
                              int id, size_t *reqDataLen)
91
 
{
92
 
        int res;
93
 
        u8 *req;
94
 
 
95
 
        res = eap_server_tls_buildReq_helper(sm, &data->ssl, EAP_TYPE_TLS, 0,
96
 
                                             id, &req, reqDataLen);
97
 
 
98
 
        if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
99
 
                wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
100
 
                data->state = SUCCESS;
101
 
        }
102
 
 
103
 
        if (res == 1)
104
 
                return eap_server_tls_build_ack(reqDataLen, id, EAP_TYPE_TLS,
105
 
                                                0);
106
 
        return req;
107
 
}
108
 
 
109
 
 
110
 
static u8 * eap_tls_buildReq(struct eap_sm *sm, void *priv, int id,
111
 
                             size_t *reqDataLen)
112
 
{
113
 
        struct eap_tls_data *data = priv;
114
 
 
115
 
        switch (data->state) {
116
 
        case START:
117
 
                return eap_tls_build_start(sm, data, id, reqDataLen);
118
 
        case CONTINUE:
119
 
                return eap_tls_build_req(sm, data, id, reqDataLen);
120
 
        default:
121
 
                wpa_printf(MSG_DEBUG, "EAP-TLS: %s - unexpected state %d",
122
 
                           __func__, data->state);
123
 
                return NULL;
124
 
        }
125
 
}
126
 
 
127
 
 
128
 
static Boolean eap_tls_check(struct eap_sm *sm, void *priv,
129
 
                             u8 *respData, size_t respDataLen)
130
 
{
131
 
        struct eap_hdr *resp;
132
 
        u8 *pos;
133
 
 
134
 
        resp = (struct eap_hdr *) respData;
135
 
        pos = (u8 *) (resp + 1);
136
 
        if (respDataLen < sizeof(*resp) + 2 || *pos != EAP_TYPE_TLS ||
137
 
            (be_to_host16(resp->length)) > respDataLen) {
138
 
                wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame");
139
 
                return TRUE;
140
 
        }
141
 
 
142
 
        return FALSE;
143
 
}
144
 
 
145
 
 
146
 
static void eap_tls_process(struct eap_sm *sm, void *priv,
147
 
                            u8 *respData, size_t respDataLen)
148
 
{
149
 
        struct eap_tls_data *data = priv;
150
 
        struct eap_hdr *resp;
151
 
        u8 *pos, flags;
152
 
        int left;
153
 
        unsigned int tls_msg_len;
154
 
 
155
 
        resp = (struct eap_hdr *) respData;
156
 
        pos = (u8 *) (resp + 1);
157
 
        pos++;
158
 
        flags = *pos++;
159
 
        left = be_to_host16(resp->length) - sizeof(struct eap_hdr) - 2;
160
 
        wpa_printf(MSG_DEBUG, "EAP-TLS: Received packet(len=%lu) - "
161
 
                   "Flags 0x%02x", (unsigned long) respDataLen, flags);
162
 
        if (flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) {
163
 
                if (left < 4) {
164
 
                        wpa_printf(MSG_INFO, "EAP-TLS: Short frame with TLS "
165
 
                                   "length");
166
 
                        data->state = FAILURE;
167
 
                        return;
168
 
                }
169
 
                tls_msg_len = WPA_GET_BE32(pos);
170
 
                wpa_printf(MSG_DEBUG, "EAP-TLS: TLS Message Length: %d",
171
 
                           tls_msg_len);
172
 
                if (data->ssl.tls_in_left == 0) {
173
 
                        data->ssl.tls_in_total = tls_msg_len;
174
 
                        data->ssl.tls_in_left = tls_msg_len;
175
 
                        free(data->ssl.tls_in);
176
 
                        data->ssl.tls_in = NULL;
177
 
                        data->ssl.tls_in_len = 0;
178
 
                }
179
 
                pos += 4;
180
 
                left -= 4;
181
 
        }
182
 
 
183
 
        if (eap_server_tls_process_helper(sm, &data->ssl, pos, left) < 0) {
184
 
                wpa_printf(MSG_INFO, "EAP-TLS: TLS processing failed");
185
 
                data->state = FAILURE;
186
 
                return;
187
 
        }
188
 
 
189
 
        if (tls_connection_get_write_alerts(sm->ssl_ctx, data->ssl.conn) > 1) {
190
 
                wpa_printf(MSG_INFO, "EAP-TLS: Locally detected fatal error "
191
 
                           "in TLS processing");
192
 
                data->state = FAILURE;
193
 
                return;
194
 
        }
195
 
}
196
 
 
197
 
 
198
 
static Boolean eap_tls_isDone(struct eap_sm *sm, void *priv)
199
 
{
200
 
        struct eap_tls_data *data = priv;
201
 
        return data->state == SUCCESS || data->state == FAILURE;
202
 
}
203
 
 
204
 
 
205
 
static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
206
 
{
207
 
        struct eap_tls_data *data = priv;
208
 
        u8 *eapKeyData;
209
 
 
210
 
        if (data->state != SUCCESS)
211
 
                return NULL;
212
 
 
213
 
        eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
214
 
                                               "client EAP encryption",
215
 
                                               EAP_TLS_KEY_LEN);
216
 
        if (eapKeyData) {
217
 
                *len = EAP_TLS_KEY_LEN;
218
 
                wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived key",
219
 
                            eapKeyData, EAP_TLS_KEY_LEN);
220
 
        } else {
221
 
                wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive key");
222
 
        }
223
 
 
224
 
        return eapKeyData;
225
 
}
226
 
 
227
 
 
228
 
static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
229
 
{
230
 
        struct eap_tls_data *data = priv;
231
 
        u8 *eapKeyData, *emsk;
232
 
 
233
 
        if (data->state != SUCCESS)
234
 
                return NULL;
235
 
 
236
 
        eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
237
 
                                               "client EAP encryption",
238
 
                                               EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
239
 
        if (eapKeyData) {
240
 
                emsk = malloc(EAP_EMSK_LEN);
241
 
                if (emsk)
242
 
                        memcpy(emsk, eapKeyData + EAP_TLS_KEY_LEN,
243
 
                               EAP_EMSK_LEN);
244
 
                free(eapKeyData);
245
 
        } else
246
 
                emsk = NULL;
247
 
 
248
 
        if (emsk) {
249
 
                *len = EAP_EMSK_LEN;
250
 
                wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived EMSK",
251
 
                            emsk, EAP_EMSK_LEN);
252
 
        } else {
253
 
                wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive EMSK");
254
 
        }
255
 
 
256
 
        return emsk;
257
 
}
258
 
 
259
 
 
260
 
static Boolean eap_tls_isSuccess(struct eap_sm *sm, void *priv)
261
 
{
262
 
        struct eap_tls_data *data = priv;
263
 
        return data->state == SUCCESS;
264
 
}
265
 
 
266
 
 
267
 
int eap_server_tls_register(void)
268
 
{
269
 
        struct eap_method *eap;
270
 
        int ret;
271
 
 
272
 
        eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
273
 
                                      EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
274
 
        if (eap == NULL)
275
 
                return -1;
276
 
 
277
 
        eap->init = eap_tls_init;
278
 
        eap->reset = eap_tls_reset;
279
 
        eap->buildReq = eap_tls_buildReq;
280
 
        eap->check = eap_tls_check;
281
 
        eap->process = eap_tls_process;
282
 
        eap->isDone = eap_tls_isDone;
283
 
        eap->getKey = eap_tls_getKey;
284
 
        eap->isSuccess = eap_tls_isSuccess;
285
 
        eap->get_emsk = eap_tls_get_emsk;
286
 
 
287
 
        ret = eap_server_method_register(eap);
288
 
        if (ret)
289
 
                eap_server_method_free(eap);
290
 
        return ret;
291
 
}