All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
util.c
Go to the documentation of this file.
1 /*
2  * util.c Various utility functions.
3  *
4  * Version: $Id: 6f73aefec22b48883c3198e421c6ef3030b187aa $
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000,2006 The FreeRADIUS server project
21  */
22 
23 RCSID("$Id: 6f73aefec22b48883c3198e421c6ef3030b187aa $")
24 
25 #include <freeradius-devel/radiusd.h>
26 #include <freeradius-devel/rad_assert.h>
27 
28 #include <ctype.h>
29 
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 
33 /*
34  * The signal() function in Solaris 2.5.1 sets SA_NODEFER in
35  * sa_flags, which causes grief if signal() is called in the
36  * handler before the cause of the signal has been cleared.
37  * (Infinite recursion).
38  *
39  * The same problem appears on HPUX, so we avoid it, if we can.
40  *
41  * Using sigaction() to reset the signal handler fixes the problem,
42  * so where available, we prefer that solution.
43  */
44 
45 void (*reset_signal(int signo, void (*func)(int)))(int)
46 {
47 #ifdef HAVE_SIGACTION
48  struct sigaction act, oact;
49 
50  memset(&act, 0, sizeof(act));
51  act.sa_handler = func;
52  sigemptyset(&act.sa_mask);
53  act.sa_flags = 0;
54 #ifdef SA_INTERRUPT /* SunOS */
55  act.sa_flags |= SA_INTERRUPT;
56 #endif
57  if (sigaction(signo, &act, &oact) < 0)
58  return SIG_ERR;
59  return oact.sa_handler;
60 #else
61 
62  /*
63  * re-set by calling the 'signal' function, which
64  * may cause infinite recursion and core dumps due to
65  * stack growth.
66  *
67  * However, the system is too dumb to implement sigaction(),
68  * so we don't have a choice.
69  */
70  signal(signo, func);
71 
72  return NULL;
73 #endif
74 }
75 
76 /** Create possibly many directories.
77  *
78  * @note that the input directory name is NOT treated as a constant. This is so that
79  * if an error is returned, the 'directory' ptr points to the name of the file
80  * which caused the error.
81  *
82  * @param dir path to directory to create.
83  * @param mode for new directories.
84  * @param uid to set on new directories, may be -1 to use effective uid.
85  * @param gid to set on new directories, may be -1 to use effective gid.
86  * @return
87  * - 0 on success.
88  * - -1 on failure. Error available as errno.
89  */
90 int rad_mkdir(char *dir, mode_t mode, uid_t uid, gid_t gid)
91 {
92  int rcode, fd;
93  char *p;
94 
95  /*
96  * Try to make the dir. If it exists, chmod it.
97  * If a path doesn't exist, that's OK. Otherwise
98  * return with an error.
99  *
100  * Directories permissions are initially set so
101  * that only we should have access. This prevents
102  * an attacker removing them and swapping them
103  * out for a link to somewhere else.
104  * We change them to the correct permissions later.
105  */
106  rcode = mkdir(dir, 0700);
107  if (rcode < 0) {
108  switch (errno) {
109  case EEXIST:
110  return 0; /* don't change permissions */
111 
112  case ENOENT:
113  break;
114 
115  default:
116  return rcode;
117  }
118 
119  /*
120  * A component in the dir path doesn't
121  * exist. Look for the LAST dir name. Try
122  * to create that. If there's an error, we leave
123  * the dir path as the one at which the
124  * error occured.
125  */
126  p = strrchr(dir, FR_DIR_SEP);
127  if (!p || (p == dir)) return -1;
128 
129  *p = '\0';
130  rcode = rad_mkdir(dir, mode, uid, gid);
131  if (rcode < 0) return rcode;
132 
133  /*
134  * Reset the dir path, and try again to
135  * make the dir.
136  */
137  *p = FR_DIR_SEP;
138  rcode = mkdir(dir, 0700);
139  if (rcode < 0) return rcode;
140  } /* else we successfully created the dir */
141 
142  /*
143  * Set the permissions on the directory we created
144  * this should never fail unless there's a race.
145  */
146  fd = open(dir, O_DIRECTORY);
147  if (fd < 0) return -1;
148 
149  rcode = fchmod(fd, mode);
150  if (rcode < 0) {
151  close(fd);
152  return rcode;
153  }
154 
155  if ((uid != (uid_t)-1) || (gid != (gid_t)-1)) {
156  rad_suid_up();
157  rcode = fchown(fd, uid, gid);
158  rad_suid_down();
159  }
160  close(fd);
161 
162  return rcode;
163 }
164 
165 /** Ensures that a filename cannot walk up the directory structure
166  *
167  * Also sanitizes control chars.
168  *
169  * @param request Current request (may be NULL).
170  * @param out Output buffer.
171  * @param outlen Size of the output buffer.
172  * @param in string to escape.
173  * @param arg Context arguments (unused, should be NULL).
174  */
175 size_t rad_filename_make_safe(UNUSED REQUEST *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
176 {
177  char const *q = in;
178  char *p = out;
179  size_t left = outlen;
180 
181  while (*q) {
182  if (*q != '/') {
183  if (left < 2) break;
184 
185  /*
186  * Smash control characters and spaces to
187  * something simpler.
188  */
189  if (*q < ' ') {
190  *(p++) = '_';
191  continue;
192  }
193 
194  *(p++) = *(q++);
195  left--;
196  continue;
197  }
198 
199  /*
200  * For now, allow slashes in the expanded
201  * filename. This allows the admin to set
202  * attributes which create sub-directories.
203  * Unfortunately, it also allows users to send
204  * attributes which *may* end up creating
205  * sub-directories.
206  */
207  if (left < 2) break;
208  *(p++) = *(q++);
209 
210  /*
211  * Get rid of ////../.././///.///..//
212  */
213  redo:
214  /*
215  * Get rid of ////
216  */
217  if (*q == '/') {
218  q++;
219  goto redo;
220  }
221 
222  /*
223  * Get rid of /./././
224  */
225  if ((q[0] == '.') &&
226  (q[1] == '/')) {
227  q += 2;
228  goto redo;
229  }
230 
231  /*
232  * Get rid of /../../../
233  */
234  if ((q[0] == '.') && (q[1] == '.') &&
235  (q[2] == '/')) {
236  q += 3;
237  goto redo;
238  }
239  }
240  *p = '\0';
241 
242  return (p - out);
243 }
244 
245 /** Escapes the raw string such that it should be safe to use as part of a file path
246  *
247  * This function is designed to produce a string that's still readable but portable
248  * across the majority of file systems.
249  *
250  * For security reasons it cannot remove characters from the name, and must not allow
251  * collisions to occur between different strings.
252  *
253  * With that in mind '-' has been chosen as the escape character, and will be double
254  * escaped '-' -> '--' to avoid collisions.
255  *
256  * Escaping should be reversible if the original string needs to be extracted.
257  *
258  * @note function takes additional arguments so that it may be used as an xlat escape
259  * function but it's fine to call it directly.
260  *
261  * @note OSX/Unix/NTFS/VFAT have a max filename size of 255 bytes.
262  *
263  * @param request Current request (may be NULL).
264  * @param out Output buffer.
265  * @param outlen Size of the output buffer.
266  * @param in string to escape.
267  * @param arg Context arguments (unused, should be NULL).
268  */
269 size_t rad_filename_escape(UNUSED REQUEST *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
270 {
271  size_t freespace = outlen;
272 
273  while (*in != '\0') {
274  size_t utf8_len;
275 
276  /*
277  * Encode multibyte UTF8 chars
278  */
279  utf8_len = fr_utf8_char((uint8_t const *) in, -1);
280  if (utf8_len > 1) {
281  if (freespace <= (utf8_len * 3)) break;
282 
283  switch (utf8_len) {
284  case 2:
285  snprintf(out, freespace, "-%x-%x", in[0], in[1]);
286  break;
287 
288  case 3:
289  snprintf(out, freespace, "-%x-%x-%x", in[0], in[1], in[2]);
290  break;
291 
292  case 4:
293  snprintf(out, freespace, "-%x-%x-%x-%x", in[0], in[1], in[2], in[3]);
294  break;
295  }
296 
297  freespace -= (utf8_len * 3);
298  out += (utf8_len * 3);
299  in += utf8_len;
300 
301  continue;
302  }
303 
304  /*
305  * Safe chars
306  */
307  if (((*in >= 'A') && (*in <= 'Z')) ||
308  ((*in >= 'a') && (*in <= 'z')) ||
309  ((*in >= '0') && (*in <= '9')) ||
310  (*in == '_')) {
311  if (freespace <= 1) break;
312 
313  *out++ = *in++;
314  freespace--;
315  continue;
316  }
317  if (freespace <= 2) break;
318 
319  /*
320  * Double escape '-' (like \\)
321  */
322  if (*in == '-') {
323  *out++ = '-';
324  *out++ = '-';
325 
326  freespace -= 2;
327  in++;
328  continue;
329  }
330 
331  /*
332  * Unsafe chars
333  */
334  *out++ = '-';
335  fr_bin2hex(out, (uint8_t const *)in++, 1);
336  out += 2;
337  freespace -= 3;
338  }
339  *out = '\0';
340 
341  return outlen - freespace;
342 }
343 
344 /** Converts data stored in a file name back to its original form
345  *
346  * @param out Where to write the unescaped string (may be the same as in).
347  * @param outlen Length of the output buffer.
348  * @param in Input filename.
349  * @param inlen Length of input.
350  * @return
351  * - Number of bytes written to output buffer
352  * - offset where parse error occurred on failure.
353  */
354 ssize_t rad_filename_unescape(char *out, size_t outlen, char const *in, size_t inlen)
355 {
356  char const *p, *end = in + inlen;
357  size_t freespace = outlen;
358 
359  for (p = in; p < end; p++) {
360  if (freespace <= 1) break;
361 
362  if (((*p >= 'A') && (*p <= 'Z')) ||
363  ((*p >= 'a') && (*p <= 'z')) ||
364  ((*p >= '0') && (*p <= '9')) ||
365  (*p == '_')) {
366  *out++ = *p;
367  freespace--;
368  continue;
369  }
370 
371  if (p[0] == '-') {
372  /*
373  * End of input, '-' needs at least one extra char after
374  * it to be valid.
375  */
376  if ((end - p) < 2) return in - p;
377  if (p[1] == '-') {
378  p++;
379  *out++ = '-';
380  freespace--;
381  continue;
382  }
383 
384  /*
385  * End of input, '-' must be followed by <hex><hex>
386  * but there aren't enough chars left
387  */
388  if ((end - p) < 3) return in - p;
389 
390  /*
391  * If hex2bin returns 0 the next two chars weren't hexits.
392  */
393  if (fr_hex2bin((uint8_t *) out, 1, in, 1) == 0) return in - (p + 1);
394  in += 2;
395  out++;
396  freespace--;
397  }
398 
399  return in - p; /* offset we found the bad char at */
400  }
401  *out = '\0';
402 
403  return outlen - freespace; /* how many bytes were written */
404 }
405 
406 /*
407  * Allocate memory, or exit.
408  *
409  * This call ALWAYS succeeds!
410  */
411 void *rad_malloc(size_t size)
412 {
413  void *ptr = malloc(size);
414 
415  if (ptr == NULL) {
416  ERROR("no memory");
417  fr_exit(1);
418  }
419 
420  return ptr;
421 }
422 
423 
424 void rad_const_free(void const *ptr)
425 {
426  void *tmp;
427  if (!ptr) return;
428 
429  memcpy(&tmp, &ptr, sizeof(tmp));
430  talloc_free(tmp);
431 }
432 
433 /** talloc a buffer to hold the concatenated value of all elements of argv
434  *
435  * @param ctx to allocate buffer in.
436  * @param argv array of substrings.
437  * @param argc length of array.
438  * @param c separation character. Optional, may be '\0' for no separator.
439  * @return the concatenation of the elements of argv, separated by c.
440  */
441 char *rad_ajoin(TALLOC_CTX *ctx, char const **argv, int argc, char c)
442 {
443  char *buff, *p;
444  int i;
445  size_t total = 0, freespace;
446 
447  if (!*argv) {
448  goto null;
449  }
450 
451  for (i = 0; i < argc; i++) total += (strlen(argv[i]) + ((c == '\0') ? 0 : 1));
452  if (!total) {
453  null:
454  return talloc_zero_array(ctx, char, 1);
455  }
456 
457  if (c == '\0') total++;
458 
459  freespace = total;
460  buff = p = talloc_array(ctx, char, total);
461  for (i = 0; i < argc; i++) {
462  size_t len;
463 
464  len = strlcpy(p, argv[i], freespace);
465  p += len;
466  freespace -= len;
467 
468  *p++ = c;
469  freespace--;
470  }
471  buff[total] = '\0';
472 
473  return buff;
474 }
475 
476 /*
477  * Logs an error message and aborts the program
478  *
479  */
480 
481 void NEVER_RETURNS rad_assert_fail(char const *file, unsigned int line, char const *expr)
482 {
483  ERROR("ASSERT FAILED %s[%u]: %s", file, line, expr);
484  fr_fault(SIGABRT);
485  fr_exit_now(1);
486 }
487 
488 /*
489  * Copy a quoted string.
490  */
491 int rad_copy_string(char *to, char const *from)
492 {
493  int length = 0;
494  char quote = *from;
495 
496  do {
497  if (*from == '\\') {
498  *(to++) = *(from++);
499  length++;
500  }
501  *(to++) = *(from++);
502  length++;
503  } while (*from && (*from != quote));
504 
505  if (*from != quote) return -1; /* not properly quoted */
506 
507  *(to++) = quote;
508  length++;
509  *to = '\0';
510 
511  return length;
512 }
513 
514 /*
515  * Copy a quoted string but without the quotes. The length
516  * returned is the number of chars written; the number of
517  * characters consumed is 2 more than this.
518  */
519 int rad_copy_string_bare(char *to, char const *from)
520 {
521  int length = 0;
522  char quote = *from;
523 
524  from++;
525  while (*from && (*from != quote)) {
526  if (*from == '\\') {
527  *(to++) = *(from++);
528  length++;
529  }
530  *(to++) = *(from++);
531  length++;
532  }
533 
534  if (*from != quote) return -1; /* not properly quoted */
535 
536  *to = '\0';
537 
538  return length;
539 }
540 
541 
542 /*
543  * Copy a %{} string.
544  */
545 int rad_copy_variable(char *to, char const *from)
546 {
547  int length = 0;
548  int sublen;
549 
550  *(to++) = *(from++);
551  length++;
552 
553  while (*from) {
554  switch (*from) {
555  case '"':
556  case '\'':
557  sublen = rad_copy_string(to, from);
558  if (sublen < 0) return sublen;
559  from += sublen;
560  to += sublen;
561  length += sublen;
562  break;
563 
564  case '}': /* end of variable expansion */
565  *(to++) = *(from++);
566  *to = '\0';
567  length++;
568  return length; /* proper end of variable */
569 
570  case '\\':
571  *(to++) = *(from++);
572  *(to++) = *(from++);
573  length += 2;
574  break;
575 
576  case '%': /* start of variable expansion */
577  if (from[1] == '{') {
578  *(to++) = *(from++);
579  length++;
580 
581  sublen = rad_copy_variable(to, from);
582  if (sublen < 0) return sublen;
583  from += sublen;
584  to += sublen;
585  length += sublen;
586  break;
587  } /* else FIXME: catch %%{ ?*/
588 
589  /* FALL-THROUGH */
590  default:
591  *(to++) = *(from++);
592  length++;
593  break;
594  }
595  } /* loop over the input string */
596 
597  /*
598  * We ended the string before a trailing '}'
599  */
600 
601  return -1;
602 }
603 
604 #ifndef USEC
605 #define USEC 1000000
606 #endif
607 
608 uint32_t rad_pps(uint32_t *past, uint32_t *present, time_t *then, struct timeval *now)
609 {
610  uint32_t pps;
611 
612  if (*then != now->tv_sec) {
613  *then = now->tv_sec;
614  *past = *present;
615  *present = 0;
616  }
617 
618  /*
619  * Bootstrap PPS by looking at a percentage of
620  * the previous PPS. This lets us take a moving
621  * count, without doing a moving average. If
622  * we're a fraction "f" (0..1) into the current
623  * second, we can get a good guess for PPS by
624  * doing:
625  *
626  * PPS = pps_now + pps_old * (1 - f)
627  *
628  * It's an instantaneous measurement, rather than
629  * a moving average. This will hopefully let it
630  * respond better to sudden spikes.
631  *
632  * Doing the calculations by thousands allows us
633  * to not overflow 2^32, AND to not underflow
634  * when we divide by USEC.
635  */
636  pps = USEC - now->tv_usec; /* useconds left in previous second */
637  pps /= 1000; /* scale to milliseconds */
638  pps *= *past; /* multiply by past count to get fraction */
639  pps /= 1000; /* scale to usec again */
640  pps += *present; /* add in current count */
641 
642  return pps;
643 }
644 
645 /** Split string into words and expand each one
646  *
647  * @param request Current request.
648  * @param cmd string to split.
649  * @param max_argc the maximum number of arguments to split into.
650  * @param argv Where to write the pointers into argv_buf.
651  * @param can_fail If false, stop processing if any of the xlat expansions fail.
652  * @param argv_buflen size of argv_buf.
653  * @param argv_buf temporary buffer we used to mangle/expand cmd.
654  * Pointers to offsets of this buffer will be written to argv.
655  * @return argc or -1 on failure.
656  */
657 
658 int rad_expand_xlat(REQUEST *request, char const *cmd,
659  int max_argc, char const *argv[], bool can_fail,
660  size_t argv_buflen, char *argv_buf)
661 {
662  char const *from;
663  char *to;
664  int argc = -1;
665  int i;
666  int left;
667 
668  if (strlen(cmd) > (argv_buflen - 1)) {
669  ERROR("rad_expand_xlat: Command line is too long");
670  return -1;
671  }
672 
673  /*
674  * Check for bad escapes.
675  */
676  if (cmd[strlen(cmd) - 1] == '\\') {
677  ERROR("rad_expand_xlat: Command line has final backslash, without a following character");
678  return -1;
679  }
680 
681  strlcpy(argv_buf, cmd, argv_buflen);
682 
683  /*
684  * Split the string into argv's BEFORE doing radius_xlat...
685  */
686  from = cmd;
687  to = argv_buf;
688  argc = 0;
689  while (*from) {
690  int length;
691 
692  /*
693  * Skip spaces.
694  */
695  if ((*from == ' ') || (*from == '\t')) {
696  from++;
697  continue;
698  }
699 
700  argv[argc] = to;
701  argc++;
702 
703  if (argc >= (max_argc - 1)) break;
704 
705  /*
706  * Copy the argv over to our buffer.
707  */
708  while (*from && (*from != ' ') && (*from != '\t')) {
709  if (to >= argv_buf + argv_buflen - 1) {
710  ERROR("rad_expand_xlat: Ran out of space in command line");
711  return -1;
712  }
713 
714  switch (*from) {
715  case '"':
716  case '\'':
717  length = rad_copy_string_bare(to, from);
718  if (length < 0) {
719  ERROR("rad_expand_xlat: Invalid string passed as argument");
720  return -1;
721  }
722  from += length+2;
723  to += length;
724  break;
725 
726  case '%':
727  if (from[1] == '{') {
728  *(to++) = *(from++);
729 
730  length = rad_copy_variable(to, from);
731  if (length < 0) {
732  ERROR("rad_expand_xlat: Invalid variable expansion passed as argument");
733  return -1;
734  }
735  from += length;
736  to += length;
737  } else { /* FIXME: catch %%{ ? */
738  *(to++) = *(from++);
739  }
740  break;
741 
742  case '\\':
743  if (from[1] == ' ') from++;
744  /* FALL-THROUGH */
745 
746  default:
747  *(to++) = *(from++);
748  }
749  } /* end of string, or found a space */
750 
751  *(to++) = '\0'; /* terminate the string */
752  }
753 
754  /*
755  * We have to have SOMETHING, at least.
756  */
757  if (argc <= 0) {
758  ERROR("rad_expand_xlat: Empty command line");
759  return -1;
760  }
761 
762  /*
763  * Expand each string, as appropriate.
764  */
765  left = argv_buf + argv_buflen - to;
766  for (i = 0; i < argc; i++) {
767  int sublen;
768 
769  /*
770  * Don't touch argv's which won't be translated.
771  */
772  if (strchr(argv[i], '%') == NULL) continue;
773 
774  if (!request) continue;
775 
776  sublen = radius_xlat(to, left - 1, request, argv[i], NULL, NULL);
777  if (sublen <= 0) {
778  if (can_fail) {
779  /*
780  * Fail to be backwards compatible.
781  *
782  * It's yucky, but it won't break anything,
783  * and it won't cause security problems.
784  */
785  sublen = 0;
786  } else {
787  ERROR("rad_expand_xlat: xlat failed");
788  return -1;
789  }
790  }
791 
792  argv[i] = to;
793  to += sublen;
794  *(to++) = '\0';
795  left -= sublen;
796  left--;
797 
798  if (left <= 0) {
799  ERROR("rad_expand_xlat: Ran out of space while expanding arguments");
800  return -1;
801  }
802  }
803  argv[argc] = NULL;
804 
805  return argc;
806 }
807 
808 /** Return the default log dir
809  *
810  * This is set at build time from --prefix
811  * @return the value of LOGDIR
812  */
813 char const *rad_default_log_dir(void)
814 {
815  return LOGDIR;
816 }
817 
818 /** Return the default lib dir
819  *
820  * This is set at build time from --prefix
821  * @return the value of LIBDIR
822  */
823 char const *rad_default_lib_dir(void)
824 {
825  return LIBDIR;
826 }
827 
828 /** Return the default raddb dir
829  *
830  * This is set at build time from --prefix
831  * @return the value of RADDBDIR
832  */
833 char const *rad_default_raddb_dir(void)
834 {
835  return RADDBDIR;
836 }
837 
838 /** Return the default run dir
839  *
840  * This is set at build time from --prefix
841  * @return the value of RUNDIR
842  */
843 char const *rad_default_run_dir(void)
844 {
845  return RUNDIR;
846 }
847 
848 /** Return the default sbin dir
849  *
850  * This is set at build time from --prefix
851  * @return the value of SBINDIR
852  */
853 char const *rad_default_sbin_dir(void)
854 {
855  return SBINDIR;
856 }
857 
858 /** Return the default radacct dir
859  *
860  * This is set at build time from --prefix
861  * @return the value of RADIR
862  */
863 char const *rad_radacct_dir(void)
864 {
865  return RADIR;
866 }
867 
868 #ifndef NDEBUG
869 /*
870  * Verify a packet.
871  */
872 static void verify_packet(char const *file, int line, REQUEST *request, RADIUS_PACKET *packet, char const *type)
873 {
874  TALLOC_CTX *parent;
875 
876  if (!packet) {
877  fprintf(stderr, "CONSISTENCY CHECK FAILED %s[%i]: RADIUS_PACKET %s pointer was NULL", file, line, type);
878  fr_assert(0);
879  fr_exit_now(0);
880  }
881 
882  parent = talloc_parent(packet);
883  if (parent != request) {
884  ERROR("CONSISTENCY CHECK FAILED %s[%i]: Expected RADIUS_PACKET %s to be parented by %p (%s), "
885  "but parented by %p (%s)", file, line, type, request, talloc_get_name(request),
886  parent, parent ? talloc_get_name(parent) : "NULL");
887 
888  fr_log_talloc_report(packet);
889  if (parent) fr_log_talloc_report(parent);
890 
891  rad_assert(0);
892  }
893 
894  VERIFY_PACKET(packet);
895 
896  if (!packet->vps) return;
897 
898 #ifdef WITH_VERIFY_PTR
899  fr_pair_list_verify(file, line, packet, packet->vps);
900 #endif
901 }
902 /*
903  * Catch horrible talloc errors.
904  */
905 void verify_request(char const *file, int line, REQUEST *request)
906 {
907  if (!request) {
908  fprintf(stderr, "CONSISTENCY CHECK FAILED %s[%i]: REQUEST pointer was NULL", file, line);
909  fr_assert(0);
910  fr_exit_now(0);
911  }
912 
913  (void) talloc_get_type_abort(request, REQUEST);
914 
915 #ifdef WITH_VERIFY_PTR
916  fr_pair_list_verify(file, line, request, request->config);
917  fr_pair_list_verify(file, line, request->state_ctx, request->state);
918 #endif
919 
920  if (request->packet) verify_packet(file, line, request, request->packet, "request");
921  if (request->reply) verify_packet(file, line, request, request->reply, "reply");
922 #ifdef WITH_PROXY
923  if (request->proxy) verify_packet(file, line, request, request->proxy, "proxy-request");
924  if (request->proxy_reply) verify_packet(file, line, request, request->proxy_reply, "proxy-reply");
925 #endif
926 
927 #ifdef WITH_COA
928  if (request->coa) {
929  void *parent;
930 
931  (void) talloc_get_type_abort(request->coa, REQUEST);
932  parent = talloc_parent(request->coa);
933 
934  rad_assert(parent == request);
935 
936  verify_request(file, line, request->coa);
937  }
938 #endif
939 }
940 #endif
941 
942 /** Convert mode_t into humanly readable permissions flags
943  *
944  * @author Jonathan Leffler.
945  *
946  * @param mode to convert.
947  * @param out Where to write the string to, must be exactly 10 bytes long.
948  */
949 void rad_mode_to_str(char out[10], mode_t mode)
950 {
951  static char const *rwx[] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"};
952 
953  strcpy(&out[0], rwx[(mode >> 6) & 0x07]);
954  strcpy(&out[3], rwx[(mode >> 3) & 0x07]);
955  strcpy(&out[6], rwx[(mode & 7)]);
956  if (mode & S_ISUID) out[2] = (mode & 0100) ? 's' : 'S';
957  if (mode & S_ISGID) out[5] = (mode & 0010) ? 's' : 'l';
958  if (mode & S_ISVTX) out[8] = (mode & 0100) ? 't' : 'T';
959  out[9] = '\0';
960 }
961 
962 void rad_mode_to_oct(char out[5], mode_t mode)
963 {
964  out[0] = '0' + ((mode >> 9) & 0x07);
965  out[1] = '0' + ((mode >> 6) & 0x07);
966  out[2] = '0' + ((mode >> 3) & 0x07);
967  out[3] = '0' + (mode & 0x07);
968  out[4] = '\0';
969 }
970 
971 /** Resolve a uid to a passwd entry
972  *
973  * Resolves a uid to a passwd entry. The memory to hold the
974  * passwd entry is talloced under ctx, and must be freed when no
975  * longer required.
976  *
977  * @param ctx to allocate passwd entry in.
978  * @param out Where to write pointer to entry.
979  * @param uid to resolve.
980  * @return
981  * - 0 on success.
982  * - -1 on failure.
983  */
984 int rad_getpwuid(TALLOC_CTX *ctx, struct passwd **out, uid_t uid)
985 {
986  static size_t len;
987  uint8_t *buff;
988  int ret;
989 
990  *out = NULL;
991 
992  /*
993  * We assume this won't change between calls,
994  * and that the value is the same, so races don't
995  * matter.
996  */
997  if (len == 0) {
998 #ifdef _SC_GETPW_R_SIZE_MAX
999  long int sc_len;
1000 
1001  sc_len = sysconf(_SC_GETPW_R_SIZE_MAX);
1002  if (sc_len <= 0) sc_len = 1024;
1003  len = (size_t)sc_len;
1004 #else
1005  len = 1024;
1006 #endif
1007  }
1008 
1009  buff = talloc_array(ctx, uint8_t, sizeof(struct passwd) + len);
1010  if (!buff) return -1;
1011 
1012  /*
1013  * In some cases we may need to dynamically
1014  * grow the string buffer.
1015  */
1016  while ((ret = getpwuid_r(uid, (struct passwd *)buff, (char *)(buff + sizeof(struct passwd)),
1017  talloc_array_length(buff) - sizeof(struct passwd), out)) == ERANGE) {
1018  buff = talloc_realloc_size(ctx, buff, talloc_array_length(buff) * 2);
1019  if (!buff) {
1020  talloc_free(buff);
1021  return -1;
1022  }
1023  }
1024 
1025  if ((ret != 0) || !*out) {
1026  fr_strerror_printf("Failed resolving UID: %s", fr_syserror(ret));
1027  talloc_free(buff);
1028  errno = ret;
1029  return -1;
1030  }
1031 
1032  talloc_set_type(buff, struct passwd);
1033  *out = (struct passwd *)buff;
1034 
1035  return 0;
1036 }
1037 
1038 /** Resolve a username to a passwd entry
1039  *
1040  * Resolves a username to a passwd entry. The memory to hold the
1041  * passwd entry is talloced under ctx, and must be freed when no
1042  * longer required.
1043  *
1044  * @param ctx to allocate passwd entry in.
1045  * @param out Where to write pointer to entry.
1046  * @param name to resolve.
1047  * @return
1048  * - 0 on success.
1049  * - -1 on failure.
1050  */
1051 int rad_getpwnam(TALLOC_CTX *ctx, struct passwd **out, char const *name)
1052 {
1053  static size_t len;
1054  uint8_t *buff;
1055  int ret;
1056 
1057  *out = NULL;
1058 
1059  /*
1060  * We assume this won't change between calls,
1061  * and that the value is the same, so races don't
1062  * matter.
1063  */
1064  if (len == 0) {
1065 #ifdef _SC_GETPW_R_SIZE_MAX
1066  long int sc_len;
1067 
1068  sc_len = sysconf(_SC_GETPW_R_SIZE_MAX);
1069  if (sc_len <= 0) sc_len = 1024;
1070  len = (size_t)sc_len;
1071 #else
1072  sc_len = 1024;
1073 #endif
1074  }
1075 
1076  buff = talloc_array(ctx, uint8_t, sizeof(struct passwd) + len);
1077  if (!buff) return -1;
1078 
1079  /*
1080  * In some cases we may need to dynamically
1081  * grow the string buffer.
1082  */
1083  while ((ret = getpwnam_r(name, (struct passwd *)buff, (char *)(buff + sizeof(struct passwd)),
1084  talloc_array_length(buff) - sizeof(struct passwd), out)) == ERANGE) {
1085  buff = talloc_realloc_size(ctx, buff, talloc_array_length(buff) * 2);
1086  if (!buff) {
1087  talloc_free(buff);
1088  return -1;
1089  }
1090  }
1091 
1092  if ((ret != 0) || !*out) {
1093  fr_strerror_printf("Failed resolving UID: %s", fr_syserror(ret));
1094  talloc_free(buff);
1095  errno = ret;
1096  return -1;
1097  }
1098 
1099  talloc_set_type(buff, struct passwd);
1100  *out = (struct passwd *)buff;
1101 
1102  return 0;
1103 }
1104 
1105 /** Resolve a gid to a group database entry
1106  *
1107  * Resolves a gid to a group database entry. The memory to hold the
1108  * group entry is talloced under ctx, and must be freed when no
1109  * longer required.
1110  *
1111  * @param ctx to allocate passwd entry in.
1112  * @param out Where to write pointer to entry.
1113  * @param gid to resolve.
1114  * @return
1115  * - 0 on success.
1116  * - -1 on failure.
1117  */
1118 int rad_getgrgid(TALLOC_CTX *ctx, struct group **out, gid_t gid)
1119 {
1120  static size_t len;
1121  uint8_t *buff;
1122  int ret;
1123 
1124  *out = NULL;
1125 
1126  /*
1127  * We assume this won't change between calls,
1128  * and that the value is the same, so races don't
1129  * matter.
1130  */
1131  if (len == 0) {
1132 #ifdef _SC_GETGR_R_SIZE_MAX
1133  long int sc_len;
1134 
1135  sc_len = sysconf(_SC_GETGR_R_SIZE_MAX);
1136  if (sc_len <= 0) sc_len = 1024;
1137  len = (size_t)sc_len;
1138 #else
1139  sc_len = 1024;
1140 #endif
1141  }
1142 
1143  buff = talloc_array(ctx, uint8_t, sizeof(struct group) + len);
1144  if (!buff) return -1;
1145 
1146  /*
1147  * In some cases we may need to dynamically
1148  * grow the string buffer.
1149  */
1150  while ((ret = getgrgid_r(gid, (struct group *)buff, (char *)(buff + sizeof(struct group)),
1151  talloc_array_length(buff) - sizeof(struct group), out)) == ERANGE) {
1152  buff = talloc_realloc_size(ctx, buff, talloc_array_length(buff) * 2);
1153  if (!buff) {
1154  talloc_free(buff);
1155  return -1;
1156  }
1157  }
1158 
1159  if ((ret != 0) || !*out) {
1160  fr_strerror_printf("Failed resolving GID: %s", fr_syserror(ret));
1161  talloc_free(buff);
1162  errno = ret;
1163  return -1;
1164  }
1165 
1166  talloc_set_type(buff, struct group);
1167  *out = (struct group *)buff;
1168 
1169  return 0;
1170 }
1171 
1172 /** Resolve a group name to a group database entry
1173  *
1174  * Resolves a group name to a group database entry.
1175  * The memory to hold the group entry is talloced under ctx,
1176  * and must be freed when no longer required.
1177  *
1178  * @param ctx to allocate passwd entry in.
1179  * @param out Where to write pointer to entry.
1180  * @param name to resolve.
1181  * @return
1182  * - 0 on success.
1183  * - -1 on failure.
1184  */
1185 int rad_getgrnam(TALLOC_CTX *ctx, struct group **out, char const *name)
1186 {
1187  static size_t len;
1188  uint8_t *buff;
1189  int ret;
1190 
1191  *out = NULL;
1192 
1193  /*
1194  * We assume this won't change between calls,
1195  * and that the value is the same, so races don't
1196  * matter.
1197  */
1198  if (len == 0) {
1199 #ifdef _SC_GETGR_R_SIZE_MAX
1200  long int sc_len;
1201 
1202  sc_len = sysconf(_SC_GETGR_R_SIZE_MAX);
1203  if (sc_len <= 0) sc_len = 1024;
1204  len = (size_t)sc_len;
1205 #else
1206  len = 1024;
1207 #endif
1208  }
1209 
1210  buff = talloc_array(ctx, uint8_t, sizeof(struct group) + len);
1211  if (!buff) return -1;
1212 
1213  /*
1214  * In some cases we may need to dynamically
1215  * grow the string buffer.
1216  */
1217  while ((ret = getgrnam_r(name, (struct group *)buff, (char *)(buff + sizeof(struct group)),
1218  talloc_array_length(buff) - sizeof(struct group), out)) == ERANGE) {
1219  buff = talloc_realloc_size(ctx, buff, talloc_array_length(buff) * 2);
1220  if (!buff) {
1221  talloc_free(buff);
1222  return -1;
1223  }
1224  }
1225 
1226  if ((ret != 0) || !*out) {
1227  fr_strerror_printf("Failed resolving GID: %s", fr_syserror(ret));
1228  talloc_free(buff);
1229  errno = ret;
1230  return -1;
1231  }
1232 
1233  talloc_set_type(buff, struct group);
1234  *out = (struct group *)buff;
1235 
1236  return 0;
1237 }
1238 
1239 /** Resolve a group name to a GID
1240  *
1241  * @param ctx TALLOC_CTX for temporary allocations.
1242  * @param name of group.
1243  * @param out where to write gid.
1244  * @return
1245  * - 0 on success.
1246  * - -1 on failure.
1247  */
1248 int rad_getgid(TALLOC_CTX *ctx, gid_t *out, char const *name)
1249 {
1250  int ret;
1251  struct group *result;
1252 
1253  ret = rad_getgrnam(ctx, &result, name);
1254  if (ret < 0) return -1;
1255 
1256  *out = result->gr_gid;
1257  talloc_free(result);
1258  return 0;
1259 }
1260 
1261 /** Print uid to a string
1262  *
1263  * @param ctx TALLOC_CTX for temporary allocations.
1264  * @param uid to resolve.
1265  * @return
1266  * - 0 on success.
1267  * - -1 on failure.
1268  */
1269 char *rad_asprint_uid(TALLOC_CTX *ctx, uid_t uid)
1270 {
1271  struct passwd *result;
1272  char *out;
1273 
1274  if (rad_getpwuid(ctx, &result, uid) < 0) return NULL;
1275  out = talloc_strdup(ctx, result->pw_name);
1276  talloc_free(result);
1277 
1278  return out;
1279 }
1280 
1281 /** Print gid to a string
1282  *
1283  * @param ctx TALLOC_CTX for temporary allocations.
1284  * @param gid to resolve.
1285  * @return
1286  * - 0 on success.
1287  * - -1 on failure.
1288  */
1289 char *rad_asprint_gid(TALLOC_CTX *ctx, uid_t gid){
1290  struct group *result;
1291  char *out;
1292 
1293  if (rad_getgrgid(ctx, &result, gid) < 0) return NULL;
1294  out = talloc_strdup(ctx, result->gr_name);
1295  talloc_free(result);
1296 
1297  return out;
1298 }
1299 
1300 /** Write a file access error to the fr_strerror buffer, including euid/egid
1301  *
1302  * @note retrieve error with fr_strerror()
1303  *
1304  * @param num Usually num, unless the error is returned by the function.
1305  */
1306 void rad_file_error(int num)
1307 {
1308  char const *error;
1309  struct passwd *user = NULL;
1310  struct group *group = NULL;
1311 
1312  error = fr_syserror(num);
1313 
1314  if (rad_getpwuid(NULL, &user, geteuid()) < 0) goto finish;
1315  if (rad_getgrgid(NULL, &group, getegid()) < 0) goto finish;
1316 
1317  fr_strerror_printf("Effective user/group %s:%s: %s", user->pw_name, group->gr_name, error);
1318 finish:
1319  talloc_free(user);
1320  talloc_free(group);
1321 }
1322 
1323 #ifdef HAVE_SETUID
1324 static bool doing_setuid = false;
1325 static uid_t suid_down_uid = (uid_t)-1;
1326 
1327 /** Set the uid and gid used when dropping privileges
1328  *
1329  * @note if this function hasn't been called, rad_suid_down will have no effect.
1330  *
1331  * @param uid to drop down to.
1332  */
1333 void rad_suid_set_down_uid(uid_t uid)
1334 {
1335  suid_down_uid = uid;
1336  doing_setuid = true;
1337 }
1338 
1339 # if defined(HAVE_SETRESUID) && defined (HAVE_GETRESUID)
1340 void rad_suid_up(void)
1341 {
1342  uid_t ruid, euid, suid;
1343 
1344  if (getresuid(&ruid, &euid, &suid) < 0) {
1345  ERROR("Failed getting saved UID's");
1346  fr_exit_now(1);
1347  }
1348 
1349  if (setresuid(-1, suid, -1) < 0) {
1350  ERROR("Failed switching to privileged user");
1351  fr_exit_now(1);
1352  }
1353 
1354  if (geteuid() != suid) {
1355  ERROR("Switched to unknown UID");
1356  fr_exit_now(1);
1357  }
1358 }
1359 
1360 void rad_suid_down(void)
1361 {
1362  if (!doing_setuid) return;
1363 
1364  if (setresuid(-1, suid_down_uid, geteuid()) < 0) {
1365  struct passwd *passwd;
1366  char const *name;
1367 
1368  name = (rad_getpwuid(NULL, &passwd, suid_down_uid) < 0) ? "unknown" : passwd->pw_name;
1369  ERROR("Failed switching to uid %s: %s", name, fr_syserror(errno));
1370  talloc_free(passwd);
1371  fr_exit_now(1);
1372  }
1373 
1374  if (geteuid() != suid_down_uid) {
1375  ERROR("Failed switching uid: UID is incorrect");
1376  fr_exit_now(1);
1377  }
1378 
1380 }
1381 
1382 void rad_suid_down_permanent(void)
1383 {
1384  if (!doing_setuid) return;
1385 
1386  if (setresuid(suid_down_uid, suid_down_uid, suid_down_uid) < 0) {
1387  struct passwd *passwd;
1388  char const *name;
1389 
1390  name = (rad_getpwuid(NULL, &passwd, suid_down_uid) < 0) ? "unknown" : passwd->pw_name;
1391  ERROR("Failed in permanent switch to uid %s: %s", name, fr_syserror(errno));
1392  talloc_free(passwd);
1393  fr_exit_now(1);
1394  }
1395 
1396  if (geteuid() != suid_down_uid) {
1397  ERROR("Switched to unknown uid");
1398  fr_exit_now(1);
1399  }
1400 
1402 }
1403 # else
1404 /*
1405  * Much less secure...
1406  */
1407 void rad_suid_up(void)
1408 {
1409  if (!doing_setuid) return;
1410 
1411  if (seteuid(0) < 0) {
1412  ERROR("Failed switching up to euid 0: %s", fr_syserror(errno));
1413  fr_exit_now(1);
1414  }
1415 
1416 }
1417 
1418 void rad_suid_down(void)
1419 {
1420  if (!doing_setuid) return;
1421 
1422  if (geteuid() == suid_down_uid) return;
1423 
1424  if (seteuid(suid_down_uid) < 0) {
1425  struct passwd *passwd;
1426  char const *name;
1427 
1428  name = (rad_getpwuid(NULL, &passwd, suid_down_uid) < 0) ? "unknown": passwd->pw_name;
1429  ERROR("Failed switching to euid %s: %s", name, fr_syserror(errno));
1430  talloc_free(passwd);
1431  fr_exit_now(1);
1432  }
1433 
1435 }
1436 
1437 void rad_suid_down_permanent(void)
1438 {
1439  if (!doing_setuid) return;
1440 
1441  /*
1442  * Already done. Don't do anything else.
1443  */
1444  if (getuid() == suid_down_uid) return;
1445 
1446  /*
1447  * We're root, but running as a normal user. Fix that,
1448  * so we can call setuid().
1449  */
1450  if (geteuid() == suid_down_uid) {
1451  rad_suid_up();
1452  }
1453 
1454  if (setuid(suid_down_uid) < 0) {
1455  struct passwd *passwd;
1456  char const *name;
1457 
1458  name = (rad_getpwuid(NULL, &passwd, suid_down_uid) < 0) ? "unknown": passwd->pw_name;
1459  ERROR("Failed switching permanently to uid %s: %s", name, fr_syserror(errno));
1460  talloc_free(passwd);
1461  fr_exit_now(1);
1462  }
1463 
1465 }
1466 # endif /* HAVE_SETRESUID && HAVE_GETRESUID */
1467 #else /* HAVE_SETUID */
1468 void rad_suid_set_down_uid(uid_t uid)
1469 {
1470 }
1471 void rad_suid_up(void)
1472 {
1473 }
1474 void rad_suid_down(void)
1475 {
1477 }
1479 {
1481 }
1482 #endif /* HAVE_SETUID */
1483 
1484 /** Alter the effective user id
1485  *
1486  * @param uid to set
1487  * @return
1488  * - 0 on success.
1489  * - -1 on failure.
1490  */
1491 int rad_seuid(uid_t uid)
1492 {
1493  if (seteuid(uid) < 0) {
1494  struct passwd *passwd;
1495 
1496  if (rad_getpwuid(NULL, &passwd, uid) < 0) return -1;
1497  fr_strerror_printf("Failed setting euid to %s", passwd->pw_name);
1498  talloc_free(passwd);
1499 
1500  return -1;
1501  }
1502  return 0;
1503 }
1504 
1505 /** Alter the effective user id
1506  *
1507  * @param gid to set
1508  * @return
1509  * - 0 on success.
1510  * - -1 on failure.
1511  */
1512 int rad_segid(gid_t gid)
1513 {
1514  if (setegid(gid) < 0) {
1515  struct group *group;
1516 
1517  if (rad_getgrgid(NULL, &group, gid) < 0) return -1;
1518  fr_strerror_printf("Failed setting egid to %s", group->gr_name);
1519  talloc_free(group);
1520 
1521  return -1;
1522  }
1523  return 0;
1524 }
char const * rad_radacct_dir(void)
Return the default radacct dir.
Definition: util.c:863
char * rad_asprint_gid(TALLOC_CTX *ctx, uid_t gid)
Print gid to a string.
Definition: util.c:1289
void rad_mode_to_str(char out[10], mode_t mode)
Convert mode_t into humanly readable permissions flags.
Definition: util.c:949
VALUE_PAIR * config
VALUE_PAIR (s) used to set per request parameters for modules and the server core at runtime...
Definition: radiusd.h:227
void rad_suid_up(void)
Definition: util.c:1471
int rad_expand_xlat(REQUEST *request, char const *cmd, int max_argc, char const *argv[], bool can_fail, size_t argv_buflen, char *argv_buf)
Split string into words and expand each one.
Definition: util.c:658
RADIUS_PACKET * proxy_reply
Incoming response from proxy server.
Definition: radiusd.h:238
int rad_getgrnam(TALLOC_CTX *ctx, struct group **out, char const *name)
Resolve a group name to a group database entry.
Definition: util.c:1185
size_t rad_filename_escape(UNUSED REQUEST *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
Escapes the raw string such that it should be safe to use as part of a file path. ...
Definition: util.c:269
char const * rad_default_lib_dir(void)
Return the default lib dir.
Definition: util.c:823
void rad_suid_down_permanent(void)
Definition: util.c:1478
static char const * name
int rad_copy_string_bare(char *to, char const *from)
Definition: util.c:519
#define UNUSED
Definition: libradius.h:134
int fr_reset_dumpable(void)
Reset dumpable state to previously configured value.
Definition: debug.c:573
int rad_segid(gid_t gid)
Alter the effective user id.
Definition: util.c:1512
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
Definition: libradius.h:162
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:686
uint8_t length
Definition: proto_bfd.c:203
void rad_suid_down(void)
Definition: util.c:1474
int fr_log_talloc_report(TALLOC_CTX *ctx)
Generate a talloc memory report for a context and print to stderr/stdout.
Definition: debug.c:810
int rad_copy_string(char *to, char const *from)
Definition: util.c:491
char const * rad_default_raddb_dir(void)
Return the default raddb dir.
Definition: util.c:833
char const * rad_default_sbin_dir(void)
Return the default sbin dir.
Definition: util.c:853
RADIUS_PACKET * proxy
Outgoing request to proxy server.
Definition: radiusd.h:237
#define rad_assert(expr)
Definition: rad_assert.h:38
void rad_suid_set_down_uid(uid_t uid)
Definition: util.c:1468
void verify_request(char const *file, int line, REQUEST *request)
Definition: util.c:905
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: log.c:238
int rad_copy_variable(char *to, char const *from)
Definition: util.c:545
int rad_getgrgid(TALLOC_CTX *ctx, struct group **out, gid_t gid)
Resolve a gid to a group database entry.
Definition: util.c:1118
char * rad_asprint_uid(TALLOC_CTX *ctx, uid_t uid)
Print uid to a string.
Definition: util.c:1269
void NEVER_RETURNS rad_assert_fail(char const *file, unsigned int line, char const *expr)
Definition: util.c:481
void fr_fault(int sig)
Prints a simple backtrace (if execinfo is available) and calls panic_action if set.
Definition: debug.c:629
size_t fr_hex2bin(uint8_t *bin, size_t outlen, char const *hex, size_t inlen)
Convert hex strings to binary data.
Definition: misc.c:220
REQUEST * coa
CoA request originated by this request.
Definition: radiusd.h:307
TALLOC_CTX * state_ctx
for request->state
Definition: radiusd.h:230
uint32_t rad_pps(uint32_t *past, uint32_t *present, time_t *then, struct timeval *now)
Definition: util.c:608
void * rad_malloc(size_t size)
Definition: util.c:411
#define USEC
Definition: util.c:605
#define fr_assert(_x)
Definition: libradius.h:505
int rad_getgid(TALLOC_CTX *ctx, gid_t *out, char const *name)
Resolve a group name to a GID.
Definition: util.c:1248
RADIUS_PACKET * reply
Outgoing response.
Definition: radiusd.h:225
char const * rad_default_log_dir(void)
Return the default log dir.
Definition: util.c:813
#define VERIFY_PACKET(_x)
Definition: pair.h:46
ssize_t radius_xlat(char *out, size_t outlen, REQUEST *request, char const *fmt, xlat_escape_t escape, void *escape_ctx) CC_HINT(nonnull(1
char const * rad_default_run_dir(void)
Return the default run dir.
Definition: util.c:843
ssize_t rad_filename_unescape(char *out, size_t outlen, char const *in, size_t inlen)
Converts data stored in a file name back to its original form.
Definition: util.c:354
int rad_mkdir(char *dir, mode_t mode, uid_t uid, gid_t gid)
Create possibly many directories.
Definition: util.c:90
void rad_mode_to_oct(char out[5], mode_t mode)
Definition: util.c:962
char * rad_ajoin(TALLOC_CTX *ctx, char const **argv, int argc, char c)
talloc a buffer to hold the concatenated value of all elements of argv
Definition: util.c:441
int rad_getpwuid(TALLOC_CTX *ctx, struct passwd **out, uid_t uid)
Resolve a uid to a passwd entry.
Definition: util.c:984
static void verify_packet(char const *file, int line, REQUEST *request, RADIUS_PACKET *packet, char const *type)
Definition: util.c:872
VALUE_PAIR * state
VALUE_PAIR (s) available over the lifetime of the authentication attempt.
Definition: radiusd.h:231
size_t rad_filename_make_safe(UNUSED REQUEST *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
Ensures that a filename cannot walk up the directory structure.
Definition: util.c:175
int rad_seuid(uid_t uid)
Alter the effective user id.
Definition: util.c:1491
RADIUS_PACKET * packet
Incoming request.
Definition: radiusd.h:221
#define fr_exit_now(_x)
Definition: libradius.h:511
void fr_strerror_printf(char const *,...) CC_HINT(format(printf
int rad_getpwnam(TALLOC_CTX *ctx, struct passwd **out, char const *name)
Resolve a username to a passwd entry.
Definition: util.c:1051
void rad_const_free(void const *ptr)
Definition: util.c:424
void(*)(int) reset_signal(int signo, void(*func)(int))
Definition: util.c:45
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:38
int fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
Definition: print.c:34
#define NEVER_RETURNS
Definition: libradius.h:133
#define RCSID(id)
Definition: build.h:135
#define fr_exit(_x)
Definition: libradius.h:508
size_t fr_bin2hex(char *hex, uint8_t const *bin, size_t inlen)
Convert binary data to a hex string.
Definition: misc.c:254
#define ERROR(fmt,...)
Definition: log.h:145
void rad_file_error(int num)
Write a file access error to the fr_strerror buffer, including euid/egid.
Definition: util.c:1306