23RCSID(
"$Id: 7f5c2d4a90910e9bc2e5593729b491d3676283c3 $")
25#include <freeradius-devel/server/base.h>
27#include <freeradius-devel/util/base16.h>
28#include <freeradius-devel/util/perm.h>
50 struct sigaction act, oact;
52 memset(&act, 0,
sizeof(act));
53 act.sa_handler = func;
54 sigemptyset(&act.sa_mask);
57 act.sa_flags |= SA_INTERRUPT;
59 if (sigaction(signo, &act, &oact) < 0)
61 return oact.sa_handler;
148 if ((q[0] ==
'.') && (q[1] ==
'.') &&
164 if (vb->vb_length == 0)
return 0;
171 MEM(escaped = talloc_array(vb,
char, vb->vb_length + 1));
206 size_t freespace = outlen;
208 while (*
in !=
'\0') {
216 if (freespace <= (utf8_len * 3))
break;
232 freespace -= (utf8_len * 3);
233 out += (utf8_len * 3);
242 if (((*
in >=
'A') && (*
in <=
'Z')) ||
243 ((*
in >=
'a') && (*
in <=
'z')) ||
244 ((*
in >=
'0') && (*
in <=
'9')) ||
246 if (freespace <= 1)
break;
252 if (freespace <= 2)
break;
277 return outlen - freespace;
285 if (vb->vb_length == 0)
return 0;
293 MEM(escaped = talloc_array(vb,
char, vb->vb_length * 3 + 1));
300 if (len == vb->vb_length) {
322 char const *p, *end =
in +
inlen;
323 size_t freespace = outlen;
325 for (p =
in; p < end; p++) {
326 if (freespace <= 1)
break;
328 if (((*p >=
'A') && (*p <=
'Z')) ||
329 ((*p >=
'a') && (*p <=
'z')) ||
330 ((*p >=
'0') && (*p <=
'9')) ||
342 if ((end - p) < 2)
return in - p;
354 if ((end - p) < 3)
return in - p;
371 return outlen - freespace;
382char *
rad_ajoin(TALLOC_CTX *ctx,
char const **argv,
int argc,
char c)
386 size_t total = 0, freespace;
392 for (i = 0; i < argc; i++) total += (strlen(argv[i]) + ((c ==
'\0') ? 0 : 1));
395 return talloc_zero_array(ctx,
char, 1);
398 if (c ==
'\0') total++;
401 buff = p = talloc_array(ctx,
char, total);
402 for (i = 0; i < argc; i++) {
405 len =
strlcpy(p, argv[i], freespace);
432 }
while (*from && (*from != quote));
434 if (*from != quote)
return -1;
454 while (*from && (*from != quote)) {
463 if (*from != quote)
return -1;
487 if (sublen < 0)
return sublen;
506 if (from[1] ==
'{') {
511 if (sublen < 0)
return sublen;
537 if (*then != now->tv_sec) {
561 pps =
USEC - now->tv_usec;
584 int max_argc,
char const *argv[],
bool can_fail,
585 size_t argv_buflen,
char *argv_buf)
593 if (strlen(cmd) > (argv_buflen - 1)) {
601 if (cmd[strlen(cmd) - 1] ==
'\\') {
602 fr_strerror_const(
"Expansion string ends with a trailing backslash - invalid escape sequence");
606 strlcpy(argv_buf, cmd, argv_buflen);
622 if (argc >= (max_argc - 1))
break;
627 while (*from && (*from !=
' ') && (*from !=
'\t')) {
628 if (to >= argv_buf + argv_buflen - 1) {
646 if (from[1] ==
'{') {
662 if (from[1] ==
' ') from++;
684 left = argv_buf + argv_buflen - to;
685 for (i = 0; i < argc; i++) {
691 if (strchr(argv[i],
'%') == NULL)
continue;
693 if (!request)
continue;
695 sublen =
xlat_eval(to, left - 1, request, argv[i], NULL, NULL);
728static bool doing_setuid =
false;
729static uid_t suid_down_uid = (uid_t)-1;
743# if defined(HAVE_SETRESUID) && defined (HAVE_GETRESUID)
746 uid_t ruid, euid, suid;
748 if (getresuid(&ruid, &euid, &suid) < 0) {
749 ERROR(
"Failed getting saved UID's");
753 if (setresuid(-1, suid, -1) < 0) {
754 ERROR(
"Failed switching to privileged user");
758 if (geteuid() != suid) {
759 ERROR(
"Switched to unknown UID");
766 if (!doing_setuid)
return;
768 if (setresuid(-1, suid_down_uid, geteuid()) < 0) {
769 struct passwd *passwd;
778 if (geteuid() != suid_down_uid) {
779 ERROR(
"Failed switching uid: UID is incorrect");
788 if (!doing_setuid)
return;
790 if (setresuid(suid_down_uid, suid_down_uid, suid_down_uid) < 0) {
791 struct passwd *passwd;
800 if (geteuid() != suid_down_uid) {
801 ERROR(
"Switched to unknown uid");
815 if (!doing_setuid)
return;
817 if (seteuid(0) < 0) {
826 if (!doing_setuid)
return;
828 if (geteuid() == suid_down_uid)
return;
830 if (seteuid(suid_down_uid) < 0) {
831 struct passwd *passwd;
845 if (!doing_setuid)
return;
850 if (getuid() == suid_down_uid)
return;
856 if (geteuid() == suid_down_uid) {
860 if (setuid(suid_down_uid) < 0) {
861 struct passwd *passwd;
915 if (seteuid(uid) < 0) {
916 int sete_errno = errno;
917 struct passwd *passwd;
937 if (setegid(gid) < 0) {
938 int sete_errno = errno;
#define fr_base16_encode(_out, _in)
#define fr_base16_decode(_err, _out, _in, _no_trailing)
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
int fr_reset_dumpable(void)
Reset dumpable state to previously configured value.
#define fr_exit_now(_x)
Exit without calling atexit() handlers, producing a log message in debug builds.
ssize_t rad_filename_make_safe(UNUSED request_t *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
Ensures that a filename cannot walk up the directory structure.
bool rad_suid_is_down_permanent(void)
Return whether we've permanently dropped root privileges.
static int rad_copy_string(char *to, char const *from)
static int rad_copy_variable(char *to, char const *from)
void(*)(int) reset_signal(int signo, void(*func)(int))
int rad_segid(gid_t gid)
Alter the effective user id.
uint32_t rad_pps(uint32_t *past, uint32_t *present, time_t *then, struct timeval *now)
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
int rad_filename_box_escape(fr_value_box_t *vb, UNUSED void *uxtc)
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.
static bool suid_down_permanent
Record whether we've permanently dropped privilledges.
int rad_filename_box_make_safe(fr_value_box_t *vb, UNUSED void *uxtc)
int rad_expand_xlat(request_t *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.
ssize_t rad_filename_escape(UNUSED request_t *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.
void rad_suid_down_permanent(void)
static int rad_copy_string_bare(char *to, char const *from)
int rad_seuid(uid_t uid)
Alter the effective user id.
void rad_suid_set_down_uid(uid_t uid)
ssize_t xlat_eval(char *out, size_t outlen, request_t *request, char const *fmt, xlat_escape_legacy_t escape, void const *escape_ctx)
#define fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
int fr_perm_getgrgid(TALLOC_CTX *ctx, struct group **out, gid_t gid)
Resolve a gid to a group database entry.
int fr_perm_getpwuid(TALLOC_CTX *ctx, struct passwd **out, uid_t uid)
Resolve a uid to a passwd entry.
size_t 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.
#define FR_SBUFF_IN(_start, _len_or_end)
#define FR_SBUFF_OUT(_start, _len_or_end)
static char buff[sizeof("18446744073709551615")+3]
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
size_t strlcpy(char *dst, char const *src, size_t siz)
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
#define fr_strerror_const(_msg)
void fr_value_box_strdup_shallow_replace(fr_value_box_t *vb, char const *src, ssize_t len)
Free the existing buffer (if talloced) associated with the valuebox, and replace it with a new one.
#define fr_value_box_is_safe_for(_box, _safe_for)
static size_t char fr_sbuff_t size_t inlen
static size_t char ** out