blob: a69616113dbfc2841e86a43ee94e42c0b1dc8b3f [file] [log] [blame]
Brian Waters13d96012017-12-08 16:53:31 -06001/*****************************************************************************************************
2 * Software License Agreement (BSD License)
3 * Author : Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>
4 *
5 * Copyright (c) 2009-2010, Souheil Ben Ayed, Teraoka Laboratory of Keio University, and the WIDE Project
6 * All rights reserved.
7 *
8 * Redistribution and use of this software in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by Souheil Ben Ayed <souheil@tera.ics.keio.ac.jp>.
21 *
22 * 4. Neither the name of Souheil Ben Ayed, Teraoka Laboratory of Keio University or the WIDE Project nor the
23 * names of its contributors may be used to endorse or promote products
24 * derived from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ''AS IS'' AND ANY
27 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
30 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
33 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *****************************************************************************************************/
37
38
39#include "libdiameap.h"
40
41int diameap_eap_get_code(struct eap_packet *eappacket, eap_code * eapcode)
42{
43 TRACE_ENTRY("%p %p",eappacket,eapcode);
44
45 if (eappacket->data == NULL)
46 {
47 *eapcode = ERROR;
48 TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no EAP Code to return.",DIAMEAP_EXTENSION);
49 return EINVAL;
50 }
51 if (eappacket->length < 1)
52 {
53 *eapcode = ERROR;
54 TRACE_DEBUG(INFO,"%sEAP packet length %d : no EAP Code to return.",DIAMEAP_EXTENSION, eappacket->length);
55 return EINVAL;
56 }
57 *eapcode = G8(eappacket->data);
58 return 0;
59}
60
61int diameap_eap_get_identifier(struct eap_packet *eappacket, u8 * identifier)
62{
63 TRACE_ENTRY("%p %p",eappacket,identifier);
64 *identifier = 0;
65 if (eappacket->data == NULL)
66 {
67 TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no Identifier field to return.",DIAMEAP_EXTENSION);
68 return EINVAL;
69 }
70 if (eappacket->length < 2)
71 {
72 TRACE_DEBUG(INFO,"%sEAP packet length %d : no Identifier field to return.",DIAMEAP_EXTENSION, eappacket->length);
73 return EINVAL;
74 }
75 *identifier = G8(eappacket->data + 1);
76 return 0;
77}
78
79int diameap_eap_get_length(struct eap_packet *eappacket, u16 *length)
80{
81 TRACE_ENTRY("%p %p",eappacket,length);
82 *length = 0;
83
84 if (eappacket->data == NULL)
85 {
86 TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no Length field to return.",DIAMEAP_EXTENSION);
87 return EINVAL;
88 }
89 if (eappacket->ulength < 4)
90 {
91 TRACE_DEBUG(INFO,"%sEAP packet length %d : no Length field to return.",DIAMEAP_EXTENSION, eappacket->length);
92 return EINVAL;
93 }
94 *length = (u16) G16BIGE((eappacket->data + 2));
95 return 0;
96}
97
98int diameap_eap_get_packetlength(struct eap_packet *eappacket, u16 *length)
99{
100 TRACE_ENTRY("%p %p",eappacket,length);
101 if (eappacket->data == NULL)
102 {
103 TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no Length field to return.",DIAMEAP_EXTENSION);
104 return EINVAL;
105 }
106 *length = eappacket->ulength;
107 return 0;
108}
109
110int diameap_eap_get_type(struct eap_packet *eappacket, eap_type * eaptype)
111{
112 TRACE_ENTRY("%p %p",eappacket,eaptype);
113 *eaptype = 0;
114
115 if (eappacket->data == NULL)
116 {
117 TRACE_DEBUG(INFO,"%sEmpty data in EAP packet: no EAP Type field to return.",DIAMEAP_EXTENSION);
118 return EINVAL;
119 }
120 if (eappacket->length < 5)
121 {
122 TRACE_DEBUG(INFO,"%sEAP packet length %d : no EAP Type field to return.",DIAMEAP_EXTENSION, eappacket->length);
123 return EINVAL;
124 }
125 *eaptype = (u32) G8(eappacket->data + 4);
126 return 0;
127}
128
129boolean diameap_eap_check_code(eap_code code)
130{
131 TRACE_ENTRY("%d",code);
132 if (code != EAP_REQUEST && code != EAP_RESPONSE && code != EAP_SUCCESS
133 && code != EAP_FAILURE)
134 {
135 TRACE_DEBUG(FULL,"%sIncorrect EAP Code (%d).",DIAMEAP_EXTENSION,code);
136 return FALSE;
137 }
138 return TRUE;
139}
140
141int diameap_eap_get_packetdata(struct eap_packet *eappacket, u8 ** data,
142 int *len)
143{
144 TRACE_ENTRY("%p %p",eappacket,data);
145 if (eappacket->length > 0)
146 {
147 *data = malloc(sizeof(u8) * eappacket->length);
148 U8COPY(*data,0,eappacket->length,eappacket->data);
149 *len = eappacket->length;
150 return 0;
151 }
152 TRACE_DEBUG(INFO,"%sEAP packet length=%d: empty or wrong EAP Packet.",DIAMEAP_EXTENSION, eappacket->length);
153 *data = NULL;
154 *len = 0;
155 return EINVAL;
156}
157
158int diameap_eap_get_data(struct eap_packet *eappacket, u8 ** data, int * len)
159{
160 TRACE_ENTRY("%p %p",eappacket,data);
161 if (eappacket->length > 5)
162 {
163 CHECK_MALLOC( *data = malloc(sizeof(u8) * (eappacket->length - 5)) );
164 U8COPY(*data,0,(eappacket->length-5),(eappacket->data+5));
165 *len = eappacket->length - 5;
166 return 0;
167 }
168 TRACE_DEBUG(INFO,"%sEAP packet length=%d: empty or wrong EAP Packet.",DIAMEAP_EXTENSION, eappacket->length);
169 *data = NULL;
170 *len = 0;
171
172 return EINVAL;
173}
174
175void diameap_eap_dump(int level, struct eap_packet *eappacket)
176{
177 TRACE_ENTRY("%d %p",level,eappacket);
178 if (!TRACE_BOOL(level))
179 return;
180
181 if (eappacket->data == NULL)
182 return;
183 if (eappacket->length < 5)
184 return;
185 if (eappacket->ulength < 5)
186 return;
187
188 fd_log_debug("------------- Dump EAP Packet-------------");
189 int i;
190 fd_log_debug("\t -Code : ");
191 eap_code code;
192 CHECK_FCT_DO(diameap_eap_get_code(eappacket,&code),return);
193 switch (code)
194 {
195 case 1:
196 fd_log_debug("Request");
197 break;
198 case 2:
199 fd_log_debug("Response");
200 break;
201 case 3:
202 fd_log_debug("Success");
203 break;
204 case 4:
205 fd_log_debug("Failure");
206 break;
207 default:
208 fd_log_debug("Error (EAP Code value [%d] not allowed)",code);
209 break;
210 }
211 u8 id;
212 CHECK_FCT_DO(diameap_eap_get_identifier(eappacket,&id),return);
213 fd_log_debug("\t -Identifier : %x ", id);
214 u16 length;
215 CHECK_FCT_DO(diameap_eap_get_length(eappacket,&length),return);
216 fd_log_debug("\t -Length : %d ", (unsigned int)length);
217 if (eappacket->length > 4)
218 {
219 eap_type type;
220 CHECK_FCT_DO(diameap_eap_get_type(eappacket,&type),return);
221 fd_log_debug("\t -Type : %d ", type);
222 }
223 if (eappacket->length > 5)
224 {
225 char buf[1024];
226 snprintf(buf, sizeof(buf), "\t -Data : ");
227 for (i = 5; i < eappacket->length && i < 30; i++)
228 {
229 snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%02x ", G8(eappacket->data + i));
230 }
231 if(i+1<eappacket->length)
232 snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "[...] (len=%d)",(unsigned int) length);
233 fd_log_debug("%s", buf);
234 }
235 fd_log_debug("-------------End Dump EAP Packet-------------");
236}
237
238int diameap_eap_new(eap_code code, u8 id, eap_type type, u8 * data,
239 u16 dataLength, struct eap_packet *eappacket)
240{
241
242 TRACE_ENTRY("%d %hhu %d %p %hu %p", code, id, type, data, dataLength,eappacket);
243
244 int length = 0;
245
246 //Initialize EAP Packet
247 eappacket->length = 0;
248 eappacket->ulength = 0;
249 eappacket->data = NULL;
250
251 if (diameap_eap_check_code(code) == FALSE)
252 {
253 TRACE_DEBUG(
254 INFO,
255 "%sWrong EAP Code. Only Request, Response, Success or Failure are permitted.",DIAMEAP_EXTENSION);
256 return EINVAL;
257 }
258
259 length += EAP_HEADER;
260 if (code == EAP_REQUEST || code == EAP_RESPONSE)
261 { // EAP Packet code is either Request or Response
262 if (type == TYPE_NONE)
263 {
264 TRACE_DEBUG(INFO,
265 "%sUnable to create a new EAP Packet (Request or Response) without EAP Type field.",DIAMEAP_EXTENSION);
266 return EINVAL;
267 }
268 length += EAP_TYPE; // EAP Packet code
269 if (data != NULL)
270 {
271 length += dataLength;
272
273 if (length > (int) MAX_EAP_PACKET)
274 {
275
276 TRACE_DEBUG(INFO,
277 "%sUnable to add Data to EAP Packet. Data field length exceed allowed data size.", DIAMEAP_EXTENSION);
278 return EINVAL;
279 }
280 else
281 {
282
283 CHECK_MALLOC(eappacket->data=malloc(sizeof(u8)*length));
284 memset(eappacket->data, 0, sizeof(u8) * length);
285 U8COPY(eappacket->data, 5, dataLength, data);
286 }
287 }
288 else
289 {
290 CHECK_MALLOC(eappacket->data=malloc(sizeof(u8)*length));
291 memset(eappacket->data, 0, sizeof(u8) * length);
292 }
293 P8(eappacket->data + 4, type);
294 }
295 else
296 { //EAP Packet code is SUCCESS or FAILURE
297 CHECK_MALLOC(eappacket->data=malloc(sizeof(u8)*length));
298 memset(eappacket->data, 0, sizeof(u8) * length);
299 //No Data filed
300 //No Type field
301 }
302 //Add Code and Identifier fields
303 P8(eappacket->data, code);
304 P8(eappacket->data + 1, id);
305 //Add length field
306 P16BIGE(eappacket->data + 2, length);
307 eappacket->length = length;
308 eappacket->ulength = length;
309 return 0;
310}