]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libcharon/plugins/eap_ttls/eap_ttls_avp.c
Pass NULL peer identity to omit TLS peer authentication, added eap-ttls.request_peer_...
[thirdparty/strongswan.git] / src / libcharon / plugins / eap_ttls / eap_ttls_avp.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_avp.h"
17
18 #include <debug.h>
19
20 #define AVP_EAP_MESSAGE 79
21 #define AVP_HEADER_LEN 8
22
23 typedef struct private_eap_ttls_avp_t private_eap_ttls_avp_t;
24
25 /**
26 * Private data of an eap_ttls_avp_t object.
27 */
28 struct private_eap_ttls_avp_t {
29
30 /**
31 * Public eap_ttls_avp_t interface.
32 */
33 eap_ttls_avp_t public;
34
35 /**
36 * AVP input buffer
37 */
38 chunk_t input;
39
40 /**
41 * Position in input buffer
42 */
43 size_t inpos;
44
45 /**
46 * process header (TRUE) or body (FALSE)
47 */
48 bool process_header;
49
50 /**
51 * Size of AVP data
52 */
53 size_t data_len;
54 };
55
56 METHOD(eap_ttls_avp_t, build, void,
57 private_eap_ttls_avp_t *this, tls_writer_t *writer, chunk_t data)
58 {
59 char zero_padding[] = { 0x00, 0x00, 0x00 };
60 chunk_t avp_padding;
61 u_int8_t avp_flags;
62 u_int32_t avp_len;
63
64 avp_flags = 0x40;
65 avp_len = 8 + data.len;
66 avp_padding = chunk_create(zero_padding, (4 - data.len) % 4);
67
68 writer->write_uint32(writer, AVP_EAP_MESSAGE);
69 writer->write_uint8(writer, avp_flags);
70 writer->write_uint24(writer, avp_len);
71 writer->write_data(writer, data);
72 writer->write_data(writer, avp_padding);
73 }
74
75 METHOD(eap_ttls_avp_t, process, status_t,
76 private_eap_ttls_avp_t* this, tls_reader_t *reader, chunk_t *data)
77 {
78 size_t len;
79 chunk_t buf;
80
81 if (this->process_header)
82 {
83 tls_reader_t *header;
84 u_int32_t avp_code;
85 u_int8_t avp_flags;
86 u_int32_t avp_len;
87 bool success;
88
89 len = min(reader->remaining(reader), AVP_HEADER_LEN - this->inpos);
90 if (!reader->read_data(reader, len, &buf))
91 {
92 return FAILED;
93 }
94 if (this->input.len == 0)
95 {
96 /* start of a new AVP header */
97 this->input = chunk_alloc(AVP_HEADER_LEN);
98 memcpy(this->input.ptr, buf.ptr, len);
99 this->inpos = len;
100 }
101 else
102 {
103 memcpy(this->input.ptr + this->inpos, buf.ptr, len);
104 this->inpos += len;
105 }
106
107 if (this->inpos < AVP_HEADER_LEN)
108 {
109 return NEED_MORE;
110 }
111
112 /* parse AVP header */
113 header = tls_reader_create(this->input);
114 success = header->read_uint32(header, &avp_code) &&
115 header->read_uint8(header, &avp_flags) &&
116 header->read_uint24(header, &avp_len);
117 header->destroy(header);
118 chunk_free(&this->input);
119 this->inpos = 0;
120
121 if (!success)
122 {
123 DBG1(DBG_IKE, "received invalid AVP header");
124 return FAILED;
125 }
126 if (avp_code != AVP_EAP_MESSAGE)
127 {
128 DBG1(DBG_IKE, "expected AVP_EAP_MESSAGE but received %u", avp_code);
129 return FAILED;
130 }
131 this->process_header = FALSE;
132 this->data_len = avp_len - 8;
133 this->input = chunk_alloc(this->data_len + (4 - avp_len) % 4);
134 }
135
136 /* process AVP data */
137 len = min(reader->remaining(reader), this->input.len - this->inpos);
138 if (!reader->read_data(reader, len, &buf))
139 {
140 return FAILED;
141 }
142 memcpy(this->input.ptr + this->inpos, buf.ptr, len);
143 this->inpos += len;
144 if (this->inpos < this->input.len)
145 {
146 return NEED_MORE;
147 }
148
149 *data = this->input;
150 data->len = this->data_len;
151
152 /* preparing for next AVP */
153 this->input = chunk_empty;
154 this->inpos = 0;
155 this->process_header = TRUE;
156
157 return SUCCESS;
158 }
159
160 METHOD(eap_ttls_avp_t, destroy, void,
161 private_eap_ttls_avp_t *this)
162 {
163 chunk_free(&this->input);
164 free(this);
165 }
166
167 /**
168 * See header
169 */
170 eap_ttls_avp_t *eap_ttls_avp_create(void)
171 {
172 private_eap_ttls_avp_t *this;
173
174 INIT(this,
175 .public= {
176 .process = _process,
177 .build = _build,
178 .destroy = _destroy,
179 },
180 .input = chunk_empty,
181 .inpos = 0,
182 .process_header = TRUE,
183 .data_len = 0,
184 );
185
186 return &this->public;
187 }