~ubuntu-branches/ubuntu/vivid/wpasupplicant/vivid

« back to all changes in this revision

Viewing changes to src/eap_server/eap_tls_common.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2008-03-12 20:03:04 UTC
  • mfrom: (1.1.10 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080312200304-4331y9wj46pdd34z
Tags: 0.6.3-1
* New upstream release.
* Drop patches applied upstream:
  - debian/patches/30_wpa_gui_qt4_eventhistoryui_rework.patch
  - debian/patches/31_wpa_gui_qt4_eventhistory_always_scrollbar.patch
  - debian/patches/32_wpa_gui_qt4_eventhistory_scroll_with_events.patch
  - debian/patches/40_dbus_ssid_data.patch
* Tidy up the clean target of debian/rules. Now that the madwifi headers are
  handled differently we no longer need to do any cleanup.
* Fix formatting error in debian/ifupdown/wpa_action.8 to make lintian
  quieter.
* Add patch to fix formatting errors in manpages build from sgml source. Use
  <emphasis> tags to hightlight keywords instead of surrounding them in
  strong quotes.
  - debian/patches/41_manpage_format_fixes.patch
* wpasupplicant binary package no longer suggests pcscd, guessnet, iproute
  or wireless-tools, nor does it recommend dhcp3-client. These are not
  needed.
* Add debian/patches/10_silence_siocsiwauth_icotl_failure.patch to disable
  ioctl failure messages that occur under normal conditions.
* Cherry pick two upstream git commits concerning the dbus interface:
  - debian/patches/11_avoid_dbus_version_namespace.patch
  - debian/patches/12_fix_potential_use_after_free.patch
* Add debian/patches/42_manpage_explain_available_drivers.patch to explain
  that not all of the driver backends are available in the provided
  wpa_supplicant binary, and that the canonical list of supported driver
  backends can be retrieved from the wpa_supplicant -h (help) output.
  (Closes: #466910)
* Add debian/patches/20_wpa_gui_qt4_disable_link_prl.patch to remove
  link_prl CONFIG compile flag added by qmake-qt4 >= 4.3.4-2 to avoid excess
  linking.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * hostapd / EAP-TLS/PEAP/TTLS/FAST common functions
 
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 "sha1.h"
 
21
#include "tls.h"
 
22
 
 
23
 
 
24
int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
 
25
                            int verify_peer)
 
26
{
 
27
        data->eap = sm;
 
28
        data->phase2 = sm->init_phase2;
 
29
 
 
30
        data->conn = tls_connection_init(sm->ssl_ctx);
 
31
        if (data->conn == NULL) {
 
32
                wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS "
 
33
                           "connection");
 
34
                return -1;
 
35
        }
 
36
 
 
37
        if (tls_connection_set_verify(sm->ssl_ctx, data->conn, verify_peer)) {
 
38
                wpa_printf(MSG_INFO, "SSL: Failed to configure verification "
 
39
                           "of TLS peer certificate");
 
40
                tls_connection_deinit(sm->ssl_ctx, data->conn);
 
41
                data->conn = NULL;
 
42
                return -1;
 
43
        }
 
44
 
 
45
        /* TODO: make this configurable */
 
46
        data->tls_out_limit = 1398;
 
47
        if (data->phase2) {
 
48
                /* Limit the fragment size in the inner TLS authentication
 
49
                 * since the outer authentication with EAP-PEAP does not yet
 
50
                 * support fragmentation */
 
51
                if (data->tls_out_limit > 100)
 
52
                        data->tls_out_limit -= 100;
 
53
        }
 
54
        return 0;
 
55
}
 
56
 
 
57
 
 
58
void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
 
59
{
 
60
        tls_connection_deinit(sm->ssl_ctx, data->conn);
 
61
        os_free(data->tls_in);
 
62
        os_free(data->tls_out);
 
63
}
 
64
 
 
65
 
 
66
u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
 
67
                               char *label, size_t len)
 
68
{
 
69
        struct tls_keys keys;
 
70
        u8 *rnd = NULL, *out;
 
71
 
 
72
        out = os_malloc(len);
 
73
        if (out == NULL)
 
74
                return NULL;
 
75
 
 
76
        if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) ==
 
77
            0)
 
78
                return out;
 
79
 
 
80
        if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys))
 
81
                goto fail;
 
82
 
 
83
        if (keys.client_random == NULL || keys.server_random == NULL ||
 
84
            keys.master_key == NULL)
 
85
                goto fail;
 
86
 
 
87
        rnd = os_malloc(keys.client_random_len + keys.server_random_len);
 
88
        if (rnd == NULL)
 
89
                goto fail;
 
90
        os_memcpy(rnd, keys.client_random, keys.client_random_len);
 
91
        os_memcpy(rnd + keys.client_random_len, keys.server_random,
 
92
                  keys.server_random_len);
 
93
 
 
94
        if (tls_prf(keys.master_key, keys.master_key_len,
 
95
                    label, rnd, keys.client_random_len +
 
96
                    keys.server_random_len, out, len))
 
97
                goto fail;
 
98
 
 
99
        os_free(rnd);
 
100
        return out;
 
101
 
 
102
fail:
 
103
        os_free(out);
 
104
        os_free(rnd);
 
105
        return NULL;
 
106
}
 
107
 
 
108
 
 
109
int eap_server_tls_data_reassemble(struct eap_sm *sm,
 
110
                                   struct eap_ssl_data *data,
 
111
                                   u8 **in_data, size_t *in_len)
 
112
{
 
113
        u8 *buf;
 
114
 
 
115
        if (data->tls_in_left > *in_len || data->tls_in) {
 
116
                if (*in_len == 0) {
 
117
                        wpa_printf(MSG_INFO, "SSL: Empty fragment when trying "
 
118
                                   "to reassemble");
 
119
                        return -1;
 
120
                }
 
121
                if (data->tls_in_len + *in_len > 65536) {
 
122
                        /* Limit length to avoid rogue peers from causing large
 
123
                         * memory allocations. */
 
124
                        os_free(data->tls_in);
 
125
                        data->tls_in = NULL;
 
126
                        data->tls_in_len = 0;
 
127
                        wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size"
 
128
                                   " over 64 kB)");
 
129
                        return -1;
 
130
                }
 
131
                buf = os_realloc(data->tls_in, data->tls_in_len + *in_len);
 
132
                if (buf == NULL) {
 
133
                        os_free(data->tls_in);
 
134
                        data->tls_in = NULL;
 
135
                        data->tls_in_len = 0;
 
136
                        wpa_printf(MSG_INFO, "SSL: Could not allocate memory "
 
137
                                   "for TLS data");
 
138
                        return -1;
 
139
                }
 
140
                os_memcpy(buf + data->tls_in_len, *in_data, *in_len);
 
141
                data->tls_in = buf;
 
142
                data->tls_in_len += *in_len;
 
143
                if (*in_len > data->tls_in_left) {
 
144
                        wpa_printf(MSG_INFO, "SSL: more data than TLS message "
 
145
                                   "length indicated");
 
146
                        data->tls_in_left = 0;
 
147
                        return -1;
 
148
                }
 
149
                data->tls_in_left -= *in_len;
 
150
                if (data->tls_in_left > 0) {
 
151
                        wpa_printf(MSG_DEBUG, "SSL: Need %lu bytes more input "
 
152
                                   "data", (unsigned long) data->tls_in_left);
 
153
                        return 1;
 
154
                }
 
155
 
 
156
                *in_data = data->tls_in;
 
157
                *in_len = data->tls_in_len;
 
158
        } else
 
159
                data->tls_in_left = 0;
 
160
 
 
161
        return 0;
 
162
}
 
163
 
 
164
 
 
165
int eap_server_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data,
 
166
                                  const u8 *in_data, size_t in_len)
 
167
{
 
168
        WPA_ASSERT(data->tls_out_len == 0 || in_len == 0);
 
169
 
 
170
        if (data->tls_out_len == 0) {
 
171
                u8 *_in_data = (u8 *) in_data; /* FIX: get rid of the typecast
 
172
                                                */
 
173
                /* No more data to send out - expect to receive more data from
 
174
                 * the peer. */
 
175
                int res = eap_server_tls_data_reassemble(sm, data, &_in_data,
 
176
                                                         &in_len);
 
177
                if (res < 0 || res == 1) {
 
178
                        wpa_printf(MSG_DEBUG, "SSL: data reassembly failed");
 
179
                        return res;
 
180
                }
 
181
                /* Full TLS message reassembled - continue handshake processing
 
182
                 */
 
183
                if (data->tls_out) {
 
184
                        /* This should not happen.. */
 
185
                        wpa_printf(MSG_INFO, "SSL: eap_tls_process_helper - "
 
186
                                   "pending tls_out data even though "
 
187
                                   "tls_out_len = 0");
 
188
                        os_free(data->tls_out);
 
189
                        WPA_ASSERT(data->tls_out == NULL);
 
190
                }
 
191
                data->tls_out = tls_connection_server_handshake(
 
192
                        sm->ssl_ctx, data->conn, _in_data, in_len,
 
193
                        &data->tls_out_len);
 
194
 
 
195
                /* Clear reassembled input data (if the buffer was needed). */
 
196
                data->tls_in_left = data->tls_in_total = data->tls_in_len = 0;
 
197
                os_free(data->tls_in);
 
198
                data->tls_in = NULL;
 
199
        }
 
200
 
 
201
        if (data->tls_out == NULL) {
 
202
                wpa_printf(MSG_DEBUG, "SSL: failed to generate output data");
 
203
                data->tls_out_len = 0;
 
204
                return -1;
 
205
        }
 
206
        if (data->tls_out_len == 0) {
 
207
                /* TLS negotiation should now be complete since all other cases
 
208
                 * needing more that should have been catched above based on
 
209
                 * the TLS Message Length field. */
 
210
                wpa_printf(MSG_DEBUG, "SSL: No data to be sent out");
 
211
                os_free(data->tls_out);
 
212
                data->tls_out = NULL;
 
213
 
 
214
                if (tls_connection_get_read_alerts(sm->ssl_ctx, data->conn)) {
 
215
                        wpa_printf(MSG_DEBUG, "SSL: Remote end sent a fatal "
 
216
                                   "alert - abort handshake");
 
217
                        return -1;
 
218
                }
 
219
 
 
220
                return 1;
 
221
        }
 
222
 
 
223
        wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total "
 
224
                   "%lu bytes)",
 
225
                   (unsigned long) data->tls_out_len - data->tls_out_pos,
 
226
                   (unsigned long) data->tls_out_len);
 
227
 
 
228
        return 0;
 
229
}
 
230
 
 
231
 
 
232
int eap_server_tls_buildReq_helper(struct eap_sm *sm,
 
233
                                   struct eap_ssl_data *data,
 
234
                                   int eap_type, int peap_version, u8 id,
 
235
                                   struct wpabuf **out_data)
 
236
{
 
237
        size_t len;
 
238
        u8 *flags;
 
239
        struct wpabuf *req;
 
240
        int incl_len;
 
241
 
 
242
        incl_len = data->tls_out_pos == 0 &&
 
243
                data->tls_out_len > data->tls_out_limit;
 
244
        req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type,
 
245
                            1 + (incl_len ? 4 : 0) + data->tls_out_limit,
 
246
                            EAP_CODE_REQUEST, id);
 
247
        if (req == NULL) {
 
248
                *out_data = NULL;
 
249
                return -1;
 
250
        }
 
251
        flags = wpabuf_put(req, 1);
 
252
        *flags = peap_version;
 
253
        if (incl_len) {
 
254
                *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED;
 
255
                wpabuf_put_be32(req, data->tls_out_len);
 
256
        }
 
257
 
 
258
        len = data->tls_out_len - data->tls_out_pos;
 
259
        if (len > data->tls_out_limit) {
 
260
                *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS;
 
261
                len = data->tls_out_limit;
 
262
                wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments "
 
263
                           "will follow", (unsigned long) len);
 
264
        }
 
265
        wpabuf_put_data(req, &data->tls_out[data->tls_out_pos], len);
 
266
        data->tls_out_pos += len;
 
267
 
 
268
        eap_update_len(req);
 
269
        *out_data = req;
 
270
 
 
271
        if (!(*flags & EAP_TLS_FLAGS_MORE_FRAGMENTS)) {
 
272
                data->tls_out_len = 0;
 
273
                data->tls_out_pos = 0;
 
274
                os_free(data->tls_out);
 
275
                data->tls_out = NULL;
 
276
        }
 
277
 
 
278
        return 0;
 
279
}
 
280
 
 
281
 
 
282
struct wpabuf * eap_server_tls_build_ack(u8 id, int eap_type, int peap_version)
 
283
{
 
284
        struct wpabuf *req;
 
285
 
 
286
        req = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_REQUEST,
 
287
                            id);
 
288
        if (req == NULL)
 
289
                return NULL;
 
290
        wpa_printf(MSG_DEBUG, "SSL: Building ACK");
 
291
        wpabuf_put_u8(req, peap_version); /* Flags */
 
292
        return req;
 
293
}