The introduced SHA1_NOFINAL hasher was not sufficient for EAP-AKA,
[strongswan.git] / src / libstrongswan / utils.c
1 /*
2 * Copyright (C) 2005-2008 Martin Willi
3 * 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 * $Id$
16 */
17
18 #include "utils.h"
19
20 #include <string.h>
21 #include <pthread.h>
22 #include <stdio.h>
23
24 #include <enum.h>
25
26 ENUM(status_names, SUCCESS, DESTROY_ME,
27 "SUCCESS",
28 "FAILED",
29 "OUT_OF_RES",
30 "ALREADY_DONE",
31 "NOT_SUPPORTED",
32 "INVALID_ARG",
33 "NOT_FOUND",
34 "PARSE_ERROR",
35 "VERIFY_ERROR",
36 "INVALID_STATE",
37 "DESTROY_ME",
38 "NEED_MORE",
39 );
40
41 /**
42 * Described in header.
43 */
44 void *clalloc(void * pointer, size_t size)
45 {
46 void *data;
47 data = malloc(size);
48
49 memcpy(data, pointer, size);
50
51 return (data);
52 }
53
54 /**
55 * Described in header.
56 */
57 void memxor(u_int8_t dest[], u_int8_t src[], size_t n)
58 {
59 size_t i;
60 for (i = 0; i < n; i++)
61 {
62 dest[i] ^= src[i];
63 }
64 }
65
66 /**
67 * return null
68 */
69 void *return_null()
70 {
71 return NULL;
72 }
73
74 /**
75 * We use a single mutex for all refcount variables. This
76 * is not optimal for performance, but the critical section
77 * is not that long...
78 * TODO: Consider to include a mutex in each refcount_t variable.
79 */
80 static pthread_mutex_t ref_mutex = PTHREAD_MUTEX_INITIALIZER;
81
82 /**
83 * Described in header.
84 *
85 * TODO: May be implemented with atomic CPU instructions
86 * instead of a mutex.
87 */
88 void ref_get(refcount_t *ref)
89 {
90 pthread_mutex_lock(&ref_mutex);
91 (*ref)++;
92 pthread_mutex_unlock(&ref_mutex);
93 }
94
95 /**
96 * Described in header.
97 *
98 * TODO: May be implemented with atomic CPU instructions
99 * instead of a mutex.
100 */
101 bool ref_put(refcount_t *ref)
102 {
103 bool more_refs;
104
105 pthread_mutex_lock(&ref_mutex);
106 more_refs = --(*ref);
107 pthread_mutex_unlock(&ref_mutex);
108 return !more_refs;
109 }
110
111 /**
112 * output handler in printf() for time_t
113 */
114 static int time_print(FILE *stream, const struct printf_info *info,
115 const void *const *args)
116 {
117 static const char* months[] = {
118 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
119 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
120 };
121 time_t *time = *((time_t**)(args[0]));
122 bool utc = TRUE;
123 struct tm t;
124
125 if (info->alt)
126 {
127 utc = *((bool*)(args[1]));
128 }
129 if (time == UNDEFINED_TIME)
130 {
131 return fprintf(stream, "--- -- --:--:--%s----",
132 info->alt ? " UTC " : " ");
133 }
134 if (utc)
135 {
136 gmtime_r(time, &t);
137 }
138 else
139 {
140 localtime_r(time, &t);
141 }
142 return fprintf(stream, "%s %02d %02d:%02d:%02d%s%04d",
143 months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
144 t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900);
145 }
146
147 /**
148 * arginfo handler for printf() time
149 */
150 static int time_arginfo(const struct printf_info *info, size_t n, int *argtypes)
151 {
152 if (info->alt)
153 {
154 if (n > 1)
155 {
156 argtypes[0] = PA_POINTER;
157 argtypes[1] = PA_INT;
158 }
159 return 2;
160 }
161
162 if (n > 0)
163 {
164 argtypes[0] = PA_POINTER;
165 }
166 return 1;
167 }
168
169 /**
170 * output handler in printf() for time deltas
171 */
172 static int time_delta_print(FILE *stream, const struct printf_info *info,
173 const void *const *args)
174 {
175 char* unit = "second";
176 time_t *arg1, *arg2;
177 time_t delta;
178
179 arg1 = *((time_t**)(args[0]));
180 if (info->alt)
181 {
182 arg2 = *((time_t**)(args[1]));
183 delta = abs(*arg1 - *arg2);
184 }
185 else
186 {
187 delta = *arg1;
188 }
189
190 if (delta > 2 * 60 * 60 * 24)
191 {
192 delta /= 60 * 60 * 24;
193 unit = "day";
194 }
195 else if (delta > 2 * 60 * 60)
196 {
197 delta /= 60 * 60;
198 unit = "hour";
199 }
200 else if (delta > 2 * 60)
201 {
202 delta /= 60;
203 unit = "minute";
204 }
205 return fprintf(stream, "%d %s%s", delta, unit, (delta == 1)? "":"s");
206 }
207
208 /**
209 * arginfo handler for printf() time deltas
210 */
211 int time_delta_arginfo(const struct printf_info *info, size_t n, int *argtypes)
212 {
213 if (info->alt)
214 {
215 if (n > 1)
216 {
217 argtypes[0] = PA_POINTER;
218 argtypes[1] = PA_POINTER;
219 }
220 return 2;
221 }
222
223 if (n > 0)
224 {
225 argtypes[0] = PA_POINTER;
226 }
227 return 1;
228 }
229
230 /**
231 * Number of bytes per line to dump raw data
232 */
233 #define BYTES_PER_LINE 16
234
235 static char hexdig_upper[] = "0123456789ABCDEF";
236
237 /**
238 * output handler in printf() for mem ranges
239 */
240 static int mem_print(FILE *stream, const struct printf_info *info,
241 const void *const *args)
242 {
243 char *bytes = *((void**)(args[0]));
244 int len = *((size_t*)(args[1]));
245
246 char buffer[BYTES_PER_LINE * 3];
247 char ascii_buffer[BYTES_PER_LINE + 1];
248 char *buffer_pos = buffer;
249 char *bytes_pos = bytes;
250 char *bytes_roof = bytes + len;
251 int line_start = 0;
252 int i = 0;
253 int written = 0;
254
255 written += fprintf(stream, "=> %d bytes @ %p", len, bytes);
256
257 while (bytes_pos < bytes_roof)
258 {
259 *buffer_pos++ = hexdig_upper[(*bytes_pos >> 4) & 0xF];
260 *buffer_pos++ = hexdig_upper[ *bytes_pos & 0xF];
261
262 ascii_buffer[i++] =
263 (*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
264
265 if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
266 {
267 int padding = 3 * (BYTES_PER_LINE - i);
268 int written;
269
270 while (padding--)
271 {
272 *buffer_pos++ = ' ';
273 }
274 *buffer_pos++ = '\0';
275 ascii_buffer[i] = '\0';
276
277 written += fprintf(stream, "\n%4d: %s %s",
278 line_start, buffer, ascii_buffer);
279
280
281 buffer_pos = buffer;
282 line_start += BYTES_PER_LINE;
283 i = 0;
284 }
285 else
286 {
287 *buffer_pos++ = ' ';
288 }
289 }
290 return written;
291 }
292
293 /**
294 * arginfo handler for printf() mem ranges
295 */
296 int mem_arginfo(const struct printf_info *info, size_t n, int *argtypes)
297 {
298 if (n > 1)
299 {
300 argtypes[0] = PA_POINTER;
301 argtypes[1] = PA_INT;
302 }
303 return 2;
304 }
305
306 /**
307 * return printf hook functions for a time
308 */
309 printf_hook_functions_t time_get_printf_hooks()
310 {
311 printf_hook_functions_t hooks = {time_print, time_arginfo};
312
313 return hooks;
314 }
315
316 /**
317 * return printf hook functions for a time delta
318 */
319 printf_hook_functions_t time_delta_get_printf_hooks()
320 {
321 printf_hook_functions_t hooks = {time_delta_print, time_delta_arginfo};
322
323 return hooks;
324 }
325
326 /**
327 * return printf hook functions for mem ranges
328 */
329 printf_hook_functions_t mem_get_printf_hooks()
330 {
331 printf_hook_functions_t hooks = {mem_print, mem_arginfo};
332
333 return hooks;
334 }
335