~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to src/eap_peer/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
 
 * EAP peer method: EAP-TLS (RFC 2716)
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
 
#include "eap_tls_common.h"
20
 
#include "config_ssid.h"
21
 
#include "tls.h"
22
 
 
23
 
 
24
 
static void eap_tls_deinit(struct eap_sm *sm, void *priv);
25
 
 
26
 
 
27
 
struct eap_tls_data {
28
 
        struct eap_ssl_data ssl;
29
 
        u8 *key_data;
30
 
};
31
 
 
32
 
 
33
 
static void * eap_tls_init(struct eap_sm *sm)
34
 
{
35
 
        struct eap_tls_data *data;
36
 
        struct wpa_ssid *config = eap_get_config(sm);
37
 
        if (config == NULL ||
38
 
            ((sm->init_phase2 ? config->private_key2 : config->private_key)
39
 
            == NULL && config->engine == 0)) {
40
 
                wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured");
41
 
                return NULL;
42
 
        }
43
 
 
44
 
        data = os_zalloc(sizeof(*data));
45
 
        if (data == NULL)
46
 
                return NULL;
47
 
 
48
 
        if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
49
 
                wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
50
 
                eap_tls_deinit(sm, data);
51
 
                if (config->engine) {
52
 
                        wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard "
53
 
                                   "PIN");
54
 
                        eap_sm_request_pin(sm);
55
 
                        sm->ignore = TRUE;
56
 
                } else if (config->private_key && !config->private_key_passwd)
57
 
                {
58
 
                        wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private "
59
 
                                   "key passphrase");
60
 
                        eap_sm_request_passphrase(sm);
61
 
                        sm->ignore = TRUE;
62
 
                }
63
 
                return NULL;
64
 
        }
65
 
 
66
 
        return data;
67
 
}
68
 
 
69
 
 
70
 
static void eap_tls_deinit(struct eap_sm *sm, void *priv)
71
 
{
72
 
        struct eap_tls_data *data = priv;
73
 
        if (data == NULL)
74
 
                return;
75
 
        eap_peer_tls_ssl_deinit(sm, &data->ssl);
76
 
        os_free(data->key_data);
77
 
        os_free(data);
78
 
}
79
 
 
80
 
 
81
 
static u8 * eap_tls_failure(struct eap_sm *sm, struct eap_tls_data *data,
82
 
                            struct eap_method_ret *ret, int res, u8 *resp,
83
 
                            u8 id, size_t *respDataLen)
84
 
{
85
 
        wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed");
86
 
 
87
 
        ret->methodState = METHOD_DONE;
88
 
        ret->decision = DECISION_FAIL;
89
 
 
90
 
        if (res == -1) {
91
 
                struct wpa_ssid *config = eap_get_config(sm);
92
 
                if (config) {
93
 
                        /*
94
 
                         * The TLS handshake failed. So better forget the old
95
 
                         * PIN. It may be wrong, we cannot be sure but trying
96
 
                         * the wrong one again might block it on the card--so
97
 
                         * better ask the user again.
98
 
                         */
99
 
                        os_free(config->pin);
100
 
                        config->pin = NULL;
101
 
                }
102
 
        }
103
 
 
104
 
        if (resp) {
105
 
                /*
106
 
                 * This is likely an alert message, so send it instead of just
107
 
                 * ACKing the error.
108
 
                 */
109
 
                return resp;
110
 
        }
111
 
 
112
 
        return eap_peer_tls_build_ack(&data->ssl, respDataLen, id,
113
 
                                      EAP_TYPE_TLS, 0);
114
 
}
115
 
 
116
 
 
117
 
static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
118
 
                            struct eap_method_ret *ret)
119
 
{
120
 
        wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
121
 
 
122
 
        ret->methodState = METHOD_DONE;
123
 
        ret->decision = DECISION_UNCOND_SUCC;
124
 
 
125
 
        os_free(data->key_data);
126
 
        data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
127
 
                                                 "client EAP encryption",
128
 
                                                 EAP_TLS_KEY_LEN +
129
 
                                                 EAP_EMSK_LEN);
130
 
        if (data->key_data) {
131
 
                wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key",
132
 
                                data->key_data, EAP_TLS_KEY_LEN);
133
 
                wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK",
134
 
                                data->key_data + EAP_TLS_KEY_LEN,
135
 
                                EAP_EMSK_LEN);
136
 
        } else {
137
 
                wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key");
138
 
        }
139
 
}
140
 
 
141
 
 
142
 
static u8 * eap_tls_process(struct eap_sm *sm, void *priv,
143
 
                            struct eap_method_ret *ret,
144
 
                            const u8 *reqData, size_t reqDataLen,
145
 
                            size_t *respDataLen)
146
 
{
147
 
        const struct eap_hdr *req;
148
 
        size_t left;
149
 
        int res;
150
 
        u8 flags, *resp, id;
151
 
        const u8 *pos;
152
 
        struct eap_tls_data *data = priv;
153
 
 
154
 
        pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_TLS, ret,
155
 
                                        reqData, reqDataLen, &left, &flags);
156
 
        if (pos == NULL)
157
 
                return NULL;
158
 
        req = (const struct eap_hdr *) reqData;
159
 
        id = req->identifier;
160
 
 
161
 
        if (flags & EAP_TLS_FLAGS_START) {
162
 
                wpa_printf(MSG_DEBUG, "EAP-TLS: Start");
163
 
                left = 0; /* make sure that this frame is empty, even though it
164
 
                           * should always be, anyway */
165
 
        }
166
 
 
167
 
        resp = NULL;
168
 
        res = eap_peer_tls_process_helper(sm, &data->ssl, EAP_TYPE_TLS, 0, id,
169
 
                                          pos, left, &resp, respDataLen);
170
 
 
171
 
        if (res < 0) {
172
 
                return eap_tls_failure(sm, data, ret, res, resp, id,
173
 
                                       respDataLen);
174
 
        }
175
 
 
176
 
        if (tls_connection_established(sm->ssl_ctx, data->ssl.conn))
177
 
                eap_tls_success(sm, data, ret);
178
 
 
179
 
        if (res == 1) {
180
 
                os_free(resp);
181
 
                return eap_peer_tls_build_ack(&data->ssl, respDataLen, id,
182
 
                                              EAP_TYPE_TLS, 0);
183
 
        }
184
 
 
185
 
        return resp;
186
 
}
187
 
 
188
 
 
189
 
static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv)
190
 
{
191
 
        struct eap_tls_data *data = priv;
192
 
        return tls_connection_established(sm->ssl_ctx, data->ssl.conn);
193
 
}
194
 
 
195
 
 
196
 
static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv)
197
 
{
198
 
}
199
 
 
200
 
 
201
 
static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv)
202
 
{
203
 
        struct eap_tls_data *data = priv;
204
 
        os_free(data->key_data);
205
 
        data->key_data = NULL;
206
 
        if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
207
 
                os_free(data);
208
 
                return NULL;
209
 
        }
210
 
        return priv;
211
 
}
212
 
 
213
 
 
214
 
static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf,
215
 
                              size_t buflen, int verbose)
216
 
{
217
 
        struct eap_tls_data *data = priv;
218
 
        return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
219
 
}
220
 
 
221
 
 
222
 
static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv)
223
 
{
224
 
        struct eap_tls_data *data = priv;
225
 
        return data->key_data != NULL;
226
 
}
227
 
 
228
 
 
229
 
static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
230
 
{
231
 
        struct eap_tls_data *data = priv;
232
 
        u8 *key;
233
 
 
234
 
        if (data->key_data == NULL)
235
 
                return NULL;
236
 
 
237
 
        key = os_malloc(EAP_TLS_KEY_LEN);
238
 
        if (key == NULL)
239
 
                return NULL;
240
 
 
241
 
        *len = EAP_TLS_KEY_LEN;
242
 
        os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
243
 
 
244
 
        return key;
245
 
}
246
 
 
247
 
 
248
 
static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
249
 
{
250
 
        struct eap_tls_data *data = priv;
251
 
        u8 *key;
252
 
 
253
 
        if (data->key_data == NULL)
254
 
                return NULL;
255
 
 
256
 
        key = os_malloc(EAP_EMSK_LEN);
257
 
        if (key == NULL)
258
 
                return NULL;
259
 
 
260
 
        *len = EAP_EMSK_LEN;
261
 
        os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
262
 
 
263
 
        return key;
264
 
}
265
 
 
266
 
 
267
 
int eap_peer_tls_register(void)
268
 
{
269
 
        struct eap_method *eap;
270
 
        int ret;
271
 
 
272
 
        eap = eap_peer_method_alloc(EAP_PEER_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->deinit = eap_tls_deinit;
279
 
        eap->process = eap_tls_process;
280
 
        eap->isKeyAvailable = eap_tls_isKeyAvailable;
281
 
        eap->getKey = eap_tls_getKey;
282
 
        eap->get_status = eap_tls_get_status;
283
 
        eap->has_reauth_data = eap_tls_has_reauth_data;
284
 
        eap->deinit_for_reauth = eap_tls_deinit_for_reauth;
285
 
        eap->init_for_reauth = eap_tls_init_for_reauth;
286
 
        eap->get_emsk = eap_tls_get_emsk;
287
 
 
288
 
        ret = eap_peer_method_register(eap);
289
 
        if (ret)
290
 
                eap_peer_method_free(eap);
291
 
        return ret;
292
 
}