The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
misc.c
Go to the documentation of this file.
1/*
2 * This library is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2.1 of the License, or (at your option) any later version.
6 *
7 * This library is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with this library; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/** Various miscellaneous utility functions
18 *
19 * @file src/lib/util/misc.c
20 *
21 * @copyright 2000,2006 The FreeRADIUS server project
22 */
23RCSID("$Id: a690958294f1f7159bee7fe8c61427865d4d2c61 $")
24
25#include <freeradius-devel/util/dbuff.h>
26#include <freeradius-devel/util/sbuff.h>
27#include <freeradius-devel/util/syserror.h>
28
29#include <string.h>
30#include <fcntl.h>
31#include <grp.h>
32#include <pwd.h>
33#include <sys/file.h>
34#include <sys/stat.h>
35#include <sys/uio.h>
36
37#define FR_PUT_LE16(a, val)\
38 do {\
39 a[1] = ((uint16_t) (val)) >> 8;\
40 a[0] = ((uint16_t) (val)) & 0xff;\
41 } while (0)
42
43/** Sets a signal handler using sigaction if available, else signal
44 *
45 * @param sig to set handler for.
46 * @param func handler to set.
47 */
48int fr_set_signal(int sig, sig_t func)
49{
50#ifdef HAVE_SIGACTION
51 struct sigaction act;
52
53 memset(&act, 0, sizeof(act));
54 act.sa_flags = 0;
55 sigemptyset(&act.sa_mask);
56 act.sa_handler = func;
57
58 if (sigaction(sig, &act, NULL) < 0) {
59 fr_strerror_printf("Failed setting signal %i handler via sigaction(): %s", sig, fr_syserror(errno));
60 return -1;
61 }
62#else
63 if (signal(sig, func) < 0) {
64 fr_strerror_printf("Failed setting signal %i handler via signal(): %s", sig, fr_syserror(errno));
65 return -1;
66 }
67#endif
68 return 0;
69}
70
71/** Uninstall a signal for a specific handler
72 *
73 * man sigaction says these are fine to call from a signal handler.
74 *
75 * @param sig SIGNAL
76 */
77int fr_unset_signal(int sig)
78{
79#ifdef HAVE_SIGACTION
80 struct sigaction act;
81
82 memset(&act, 0, sizeof(act));
83 act.sa_flags = 0;
84 sigemptyset(&act.sa_mask);
85 act.sa_handler = SIG_DFL;
86
87 return sigaction(sig, &act, NULL);
88#else
89 return signal(sig, SIG_DFL);
90#endif
91}
92
93#ifndef F_WRLCK
94#error "missing definition for F_WRLCK, all file locks will fail"
95#endif
96
97/*
98 * cppcheck apparently can't pick this up from the system headers.
99 */
100#ifdef CPPCHECK
101#define F_WRLCK
102#endif
103
104static int rad_lock(int fd, int lock_len, int cmd, int type)
105{
106 struct flock fl;
107
108 fl.l_start = 0;
109 fl.l_len = lock_len;
110 fl.l_pid = getpid();
111 fl.l_type = type;
112 fl.l_whence = SEEK_CUR;
113
114 return fcntl(fd, cmd, (void *)&fl);
115}
116
117/*
118 * Internal wrapper for locking, to minimize the number of ifdef's
119 */
120int rad_lockfd(int fd, int lock_len)
121{
122 return rad_lock(fd, lock_len, F_SETLKW, F_WRLCK);
123}
124
125/*
126 * Internal wrapper for locking, to minimize the number of ifdef's
127 *
128 * Nonblocking version.
129 */
130int rad_lockfd_nonblock(int fd, int lock_len)
131{
132 /*
133 * Note that there's no "W" on SETLK
134 */
135 return rad_lock(fd, lock_len, F_SETLK, F_WRLCK);
136}
137
138/*
139 * Internal wrapper for unlocking, to minimize the number of ifdef's
140 * in the source.
141 */
142int rad_unlockfd(int fd, int lock_len)
143{
144 /*
145 * Note UNLOCK.
146 */
147 return rad_lock(fd, lock_len, F_SETLK, F_UNLCK);
148}
149
150/** Consume the integer (or hex) portion of a value string
151 *
152 * Allows integer or hex representations of integers (but not octal,
153 * as octal is deemed to be confusing).
154 *
155 * @param[out] out Result of parsing string as unsigned 64bit integer.
156 * @param[out] end pointer to the first non numeric char.
157 * @param[in] value string to parse.
158 *
159 * @return integer value.
160 */
161int fr_strtoull(uint64_t *out, char **end, char const *value)
162{
163 errno = 0; /* Explicitly clear errors, as glibc appears not to do this */
164
165 if ((value[0] == '0') && (value[1] == 'x')) {
166 *out = strtoull(value, end, 16);
167 if (errno == ERANGE) {
168 error:
169 fr_strerror_printf("Unsigned integer value \"%s\" too large, would overflow", value);
170 return -1;
171 }
172 return 0;
173 }
174
175 *out = strtoull(value, end, 10);
176 if (errno == ERANGE) goto error;
177 return 0;
178}
179
180/** Consume the integer (or hex) portion of a value string
181 *
182 * Allows integer or hex representations of integers (but not octal,
183 * as octal is deemed to be confusing).
184 *
185 * @note Check for overflow with errno == ERANGE.
186 *
187 * @param[out] out Result of parsing string as signed 64bit integer.
188 * @param[out] end pointer to the first non numeric char.
189 * @param[in] value string to parse.
190 * @return integer value.
191 */
192int fr_strtoll(int64_t *out, char **end, char const *value)
193{
194 errno = 0; /* Explicitly clear errors, as glibc appears not to do this */
195
196 if ((value[0] == '0') && (value[1] == 'x')) {
197 *out = strtoll(value, end, 16);
198 if (errno == ERANGE) {
199 error:
200 fr_strerror_printf("Signed integer value \"%s\" too large, would overflow", value);
201 return -1;
202 }
203 return 0;
204 }
205
206 *out = strtoll(value, end, 10);
207 if (errno == ERANGE) goto error;
208 return 0;
209}
210
211/** Trim whitespace from the end of a string
212 *
213 */
214char *fr_trim(char const *str, size_t size)
215{
216 char *q;
217
218 if (!str || !size) return NULL;
219
220 memcpy(&q, &str, sizeof(q));
221 for (q = q + size; q > str && isspace((uint8_t) *q); q--);
222
223 return q;
224}
225
226char *fr_tolower(char *str)
227{
228 char *p;
229
230 for (p = str; *p != '\0'; p++) *p = tolower(*p);
231
232 return str;
233}
234
235#ifdef O_NONBLOCK
236/** Set O_NONBLOCK on a socket
237 *
238 * @note O_NONBLOCK is POSIX.
239 *
240 * @param fd to set nonblocking flag on.
241 * @return
242 * - Flags set on the socket.
243 * - -1 on failure.
244 */
245int fr_nonblock(int fd)
246{
247 int flags;
248
249 flags = fcntl(fd, F_GETFL, NULL);
250 if (flags < 0) {
251 fr_strerror_printf("Failed getting socket flags: %s", fr_syserror(errno));
252 return -1;
253 }
254
255 flags |= O_NONBLOCK;
256 if (fcntl(fd, F_SETFL, flags) < 0) {
257 fr_strerror_printf("Failed setting socket flags: %s", fr_syserror(errno));
258 return -1;
259 }
260
261 return flags;
262}
263
264/** Unset O_NONBLOCK on a socket
265 *
266 * @note O_NONBLOCK is POSIX.
267 *
268 * @param fd to set nonblocking flag on.
269 * @return
270 * - Flags set on the socket.
271 * - -1 on failure.
272 */
273int fr_blocking(int fd)
274{
275 int flags;
276
277 flags = fcntl(fd, F_GETFL, NULL);
278 if (flags < 0) {
279 fr_strerror_printf("Failed getting socket flags: %s", fr_syserror(errno));
280 return -1;
281 }
282
283 if (!(flags & O_NONBLOCK)) return flags;
284
285 flags ^= O_NONBLOCK;
286 if (fcntl(fd, F_SETFL, flags) < 0) {
287 fr_strerror_printf("Failed setting socket flags: %s", fr_syserror(errno));
288 return -1;
289 }
290
291 return flags;
292}
293#else
295{
296 fr_strerror_const("Non blocking sockets are not supported");
297 return -1;
298}
300{
301 fr_strerror_const("Non blocking sockets are not supported");
302 return -1;
303}
304#endif
305
306/** Convert UTF8 string to UCS2 encoding
307 *
308 * @note Borrowed from src/crypto/ms_funcs.c of wpa_supplicant project (http://hostap.epitest.fi/wpa_supplicant/)
309 *
310 * @param[out] out Where to write the ucs2 string.
311 * @param[in] outlen Size of output buffer.
312 * @param[in] in UTF8 string to convert.
313 * @param[in] inlen length of UTF8 string.
314 * @return the size of the UCS2 string written to the output buffer (in bytes).
315 */
316ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
317{
318 size_t i;
319 uint8_t *start = out;
320
321 for (i = 0; i < inlen; i++) {
322 uint8_t c, c2, c3;
323
324 c = in[i];
325 if ((size_t)(out - start) >= outlen) {
326 /* input too long */
327 return -1;
328 }
329
330 /* One-byte encoding */
331 if (c <= 0x7f) {
332 out[0] = (uint8_t)c;
333 out[1] = 0;
334 out += 2;
335 continue;
336 } else if ((i == (inlen - 1)) || ((size_t)(out - start) >= (outlen - 1))) {
337 /* Incomplete surrogate */
338 return -1;
339 }
340
341 c2 = in[++i];
342 /* Two-byte encoding */
343 if ((c & 0xe0) == 0xc0) {
344 FR_PUT_LE16(out, ((c & 0x1f) << 6) | (c2 & 0x3f));
345 out += 2;
346 continue;
347 }
348 if ((i == inlen) || ((size_t)(out - start) >= (outlen - 1))) {
349 /* Incomplete surrogate */
350 return -1;
351 }
352
353 /* Three-byte encoding */
354 c3 = in[++i];
355 FR_PUT_LE16(out, ((c & 0xf) << 12) | ((c2 & 0x3f) << 6) | (c3 & 0x3f));
356 out += 2;
357 }
358
359 return out - start;
360}
361
362/** Write 128bit unsigned integer to buffer
363 *
364 * @author Alexey Frunze
365 *
366 * @param out where to write result to.
367 * @param outlen size of out.
368 * @param num 128 bit integer.
369 */
370size_t fr_snprint_uint128(char *out, size_t outlen, uint128_t const num)
371{
372 char buff[] = "00000000000000000000000000000000000000000000";
373 uint64_t n[2];
374 char *p = buff;
375 int i;
376#ifndef WORDS_BIGENDIAN
377 size_t const l = 0;
378 size_t const h = 1;
379#else
380 size_t const l = 1;
381 size_t const h = 0;
382#endif
383
384 memcpy(n, &num, sizeof(n));
385
386 for (i = 0; i < 128; i++) {
387 ssize_t j;
388 int carry;
389
390 carry = (n[h] >= 0x8000000000000000);
391
392 // Shift n[] left, doubling it
393 n[h] = ((n[h] << 1) & 0xffffffffffffffff) + (n[l] >= 0x8000000000000000);
394 n[l] = ((n[l] << 1) & 0xffffffffffffffff);
395
396 // Add s[] to itself in float, doubling it
397 for (j = sizeof(buff) - 2; j >= 0; j--) {
398 buff[j] += buff[j] - '0' + carry;
399 carry = (buff[j] > '9');
400 if (carry) buff[j] -= 10;
401 }
402 }
403
404 while ((*p == '0') && (p < &buff[sizeof(buff) - 2])) p++;
405
406 return strlcpy(out, p, outlen);
407}
408
409/** Compares two pointers
410 *
411 * @param a first pointer to compare.
412 * @param b second pointer to compare.
413 * @return
414 * - -1 if a < b.
415 * - +1 if b > a.
416 * - 0 if both equal.
417 */
418int8_t fr_pointer_cmp(void const *a, void const *b)
419{
420 return CMP(a, b);
421}
422
423/** Quick sort an array of pointers using a comparator
424 *
425 * @param to_sort array of pointers to sort.
426 * @param start the lowest index (usually 0).
427 * @param end the length of the array.
428 * @param cmp the comparison function to use to sort the array elements.
429 */
430void fr_quick_sort(void const *to_sort[], int start, int end, fr_cmp_t cmp)
431{
432 int i, pi;
433 void const *pivot;
434
435 if (start >= end) return;
436
437#define SWAP(_a, _b) \
438 do { \
439 void const *_tmp = to_sort[_a]; \
440 to_sort[_a] = to_sort[_b]; \
441 to_sort[_b] = _tmp; \
442 } while (0)
443
444 pivot = to_sort[end];
445 for (pi = start, i = start; i < end; i++) {
446 if (cmp(to_sort[i], pivot) < 0) {
447 SWAP(i , pi);
448 pi++;
449 }
450 }
451 SWAP(end, pi);
452
453 fr_quick_sort(to_sort, start, pi - 1, cmp);
454 fr_quick_sort(to_sort, pi + 1, end, cmp);
455}
456
457#ifdef TALLOC_DEBUG
458void fr_talloc_verify_cb(UNUSED const void *ptr, UNUSED int depth,
459 UNUSED int max_depth, UNUSED int is_ref,
460 UNUSED void *private_data)
461{
462 /* do nothing */
463}
464#endif
465
466
467/** Do a comparison of two authentication digests by comparing the FULL data.
468 *
469 * Otherwise, the server can be subject to timing attacks.
470 *
471 * http://www.cs.rice.edu/~dwallach/pub/crosby-timing2009.pdf
472 */
473int fr_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length)
474{
475 int result = 0;
476 size_t i;
477
478 for (i = 0; i < length; i++) result |= a[i] ^ b[i];
479
480 return result; /* 0 is OK, !0 is !OK, just like memcmp */
481}
482
483/** Get the filename from a path
484 *
485 * @param path to get filename from.
486 * @return
487 * - pointer to the filename in the path.
488 * - pointer to the path if no '/' is found.
489 */
490char const *fr_filename(char const *path)
491{
492 char const *p = strrchr(path, '/');
493
494 if (p) return p + 1;
495
496 return path;
497}
498
499/** Get the filename from a path
500 *
501 * @param path to get filename from.
502 * @return
503 * - pointer to the filename in the path.
504 * - pointer to the path if no '/' is found.
505 */
506char const *fr_filename_common_trim(char const *path, char const *common)
507{
508 char const *p_p, *p_c, *p_pn, *p_cn;
509
510 if (!path) return NULL;
511 if (!common) return NULL;
512
513 p_p = path;
514 p_c = common;
515
516 while ((p_pn = strchr(p_p, '/')) != NULL) {
517 p_cn = strchr(p_c, '/');
518 if (!p_cn) p_cn = p_c + strlen(p_c);
519
520 if ((p_pn - p_p) != (p_cn - p_c)) break; /* path component not the same len */
521 if (strncmp(p_p, p_c, p_pn - p_p) != 0) break; /* path component not the same */
522
523 p_p = p_pn + 1;
524 p_c = p_cn + 1;
525 }
526
527 return p_p;
528}
int n
Definition acutest.h:577
#define RCSID(id)
Definition build.h:485
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:112
#define UNUSED
Definition build.h:317
static fr_slen_t in
Definition dict.h:841
Test enumeration values.
Definition dict_test.h:92
long int ssize_t
unsigned char uint8_t
unsigned long int size_t
static uint8_t depth(fr_minmax_heap_index_t i)
Definition minmax_heap.c:83
void fr_quick_sort(void const *to_sort[], int start, int end, fr_cmp_t cmp)
Quick sort an array of pointers using a comparator.
Definition misc.c:430
int fr_unset_signal(int sig)
Uninstall a signal for a specific handler.
Definition misc.c:77
int fr_strtoull(uint64_t *out, char **end, char const *value)
Consume the integer (or hex) portion of a value string.
Definition misc.c:161
int fr_set_signal(int sig, sig_t func)
Sets a signal handler using sigaction if available, else signal.
Definition misc.c:48
#define FR_PUT_LE16(a, val)
Definition misc.c:37
int rad_unlockfd(int fd, int lock_len)
Definition misc.c:142
int fr_nonblock(UNUSED int fd)
Definition misc.c:294
#define SWAP(_a, _b)
char const * fr_filename_common_trim(char const *path, char const *common)
Get the filename from a path.
Definition misc.c:506
ssize_t fr_utf8_to_ucs2(uint8_t *out, size_t outlen, char const *in, size_t inlen)
Convert UTF8 string to UCS2 encoding.
Definition misc.c:316
int fr_strtoll(int64_t *out, char **end, char const *value)
Consume the integer (or hex) portion of a value string.
Definition misc.c:192
int8_t fr_pointer_cmp(void const *a, void const *b)
Compares two pointers.
Definition misc.c:418
char * fr_trim(char const *str, size_t size)
Trim whitespace from the end of a string.
Definition misc.c:214
static int rad_lock(int fd, int lock_len, int cmd, int type)
Definition misc.c:104
char * fr_tolower(char *str)
Definition misc.c:226
int rad_lockfd(int fd, int lock_len)
Definition misc.c:120
int rad_lockfd_nonblock(int fd, int lock_len)
Definition misc.c:130
int fr_blocking(UNUSED int fd)
Definition misc.c:299
char const * fr_filename(char const *path)
Get the filename from a path.
Definition misc.c:490
size_t fr_snprint_uint128(char *out, size_t outlen, uint128_t const num)
Write 128bit unsigned integer to buffer.
Definition misc.c:370
int fr_digest_cmp(uint8_t const *a, uint8_t const *b, size_t length)
Do a comparison of two authentication digests by comparing the FULL data.
Definition misc.c:473
int8_t(* fr_cmp_t)(void const *a, void const *b)
Definition misc.h:38
static char buff[sizeof("18446744073709551615")+3]
Definition size_tests.c:41
fr_aka_sim_id_type_t type
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition strlcpy.c:34
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition syserror.c:243
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
Definition strerror.h:64
#define fr_strerror_const(_msg)
Definition strerror.h:223
static size_t char fr_sbuff_t size_t inlen
Definition value.h:1020
static size_t char ** out
Definition value.h:1020