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