send tunneled EAP Identity response using eap-identity plugin
[strongswan.git] / src / libcharon / plugins / eap_ttls / eap_ttls_peer.c
1 /*
2 * Copyright (C) 2010 Andreas Steffen
3 * Copyright (C) 2010 HSR Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "eap_ttls_peer.h"
17
18 #include <debug.h>
19 #include <daemon.h>
20
21 #include <sa/authenticators/eap/eap_method.h>
22
23 #define AVP_EAP_MESSAGE 79
24
25 typedef struct private_eap_ttls_peer_t private_eap_ttls_peer_t;
26
27 /**
28 * Private data of an eap_ttls_peer_t object.
29 */
30 struct private_eap_ttls_peer_t {
31
32 /**
33 * Public eap_ttls_peer_t interface.
34 */
35 eap_ttls_peer_t public;
36
37 /**
38 * Server identity
39 */
40 identification_t *server;
41
42 /**
43 * Peer identity
44 */
45 identification_t *peer;
46
47 /**
48 * EAP-TTLS state information
49 */
50 bool start_phase2;
51 };
52
53 /**
54 * Send an EAP-Message Attribute-Value Pair
55 */
56 static void send_avp_eap_message(tls_writer_t *writer, chunk_t data)
57 {
58 char zero_padding[] = { 0x00, 0x00, 0x00 };
59 chunk_t avp_padding;
60 u_int8_t avp_flags;
61 u_int32_t avp_len;
62
63 avp_flags = 0x40;
64 avp_len = 8 + data.len;
65 avp_padding = chunk_create(zero_padding, (4 - data.len) % 4);
66
67 writer->write_uint32(writer, AVP_EAP_MESSAGE);
68 writer->write_uint8(writer, avp_flags);
69 writer->write_uint24(writer, avp_len);
70 writer->write_data(writer, data);
71 writer->write_data(writer, avp_padding);
72 }
73
74 /**
75 * Process an EAP-Message Attribute-Value Pair
76 */
77 static status_t process_avp_eap_message(tls_reader_t *reader, chunk_t *data)
78 {
79 u_int32_t avp_code;
80 u_int8_t avp_flags;
81 u_int32_t avp_len, data_len;
82
83 if (!reader->read_uint32(reader, &avp_code) ||
84 !reader->read_uint8(reader, &avp_flags) ||
85 !reader->read_uint24(reader, &avp_len))
86 {
87 DBG1(DBG_IKE, "received invalid AVP");
88 return FAILED;
89 }
90 if (avp_code != AVP_EAP_MESSAGE)
91 {
92 DBG1(DBG_IKE, "expected AVP_EAP_MESSAGE but received %u", avp_code);
93 return FAILED;
94 }
95 data_len = avp_len - 8;
96 if (!reader->read_data(reader, data_len + (4 - avp_len) % 4, data))
97 {
98 DBG1(DBG_IKE, "received insufficient AVP data");
99 return FAILED;
100 }
101 data->len = data_len;
102 return SUCCESS;
103 }
104
105 METHOD(tls_application_t, process, status_t,
106 private_eap_ttls_peer_t *this, tls_reader_t *reader)
107 {
108 chunk_t data;
109 status_t status;
110
111 status = process_avp_eap_message(reader, &data);
112 if (status == FAILED)
113 {
114 return FAILED;
115 }
116 DBG2(DBG_IKE, "received EAP message: %B", &data);
117 return FAILED;
118 }
119
120 METHOD(tls_application_t, build, status_t,
121 private_eap_ttls_peer_t *this, tls_writer_t *writer)
122 {
123 if (this->start_phase2)
124 {
125 chunk_t data;
126 eap_method_t *method;
127 eap_payload_t *res;
128
129 /* generate an EAP Identity response */
130 method = charon->eap->create_instance(charon->eap, EAP_IDENTITY, 0,
131 EAP_PEER, this->server, this->peer);
132 if (!method)
133 {
134 DBG1(DBG_IKE, "EAP_IDENTITY method not available");
135 return FAILED;
136 }
137 method->process(method, NULL, &res);
138 method->destroy(method);
139
140 /* get the raw EAP message data */
141 data = res->get_data(res);
142 DBG2(DBG_IKE, "sending EAP message: %B", &data);
143 send_avp_eap_message(writer, data);
144
145 res->destroy(res);
146 this->start_phase2 = FALSE;
147 }
148 return INVALID_STATE;
149 }
150
151 METHOD(tls_application_t, destroy, void,
152 private_eap_ttls_peer_t *this)
153 {
154 this->server->destroy(this->server);
155 this->peer->destroy(this->peer);
156 free(this);
157 }
158
159 /**
160 * See header
161 */
162 eap_ttls_peer_t *eap_ttls_peer_create(identification_t *server,
163 identification_t *peer)
164 {
165 private_eap_ttls_peer_t *this;
166
167 INIT(this,
168 .public.application = {
169 .process = _process,
170 .build = _build,
171 .destroy = _destroy,
172 },
173 .server = server->clone(server),
174 .peer = peer->clone(peer),
175 .start_phase2 = TRUE,
176 );
177
178 return &this->public;
179 }