23RCSID(
"$Id: be4a9c72971af73cbe419ba9c261ee267312856e $")
25#include <freeradius-devel/server/base.h>
27#include <freeradius-devel/util/base16.h>
28#include <freeradius-devel/util/skip.h>
29#include <freeradius-devel/util/perm.h>
30#include <freeradius-devel/util/cap.h>
52 struct sigaction act, oact;
54 memset(&act, 0,
sizeof(act));
55 act.sa_handler = func;
56 sigemptyset(&act.sa_mask);
59 act.sa_flags |= SA_INTERRUPT;
61 if (sigaction(signo, &act, &oact) < 0)
63 return oact.sa_handler;
99 if ((
size_t) (end - p) < 2)
break;
123 if ((
size_t) (end - p) < 2)
break;
150 if ((q[0] ==
'.') && (q[1] ==
'.') &&
166 if (vb->vb_length == 0)
return 0;
173 MEM(escaped = talloc_array(vb,
char, vb->vb_length + 1));
208 size_t freespace = outlen;
210 while (*
in !=
'\0') {
218 if (freespace <= (utf8_len * 3))
break;
234 freespace -= (utf8_len * 3);
235 out += (utf8_len * 3);
244 if (((*
in >=
'A') && (*
in <=
'Z')) ||
245 ((*
in >=
'a') && (*
in <=
'z')) ||
246 ((*
in >=
'0') && (*
in <=
'9')) ||
248 if (freespace <= 1)
break;
254 if (freespace <= 2)
break;
279 return outlen - freespace;
287 if (vb->vb_length == 0)
return 0;
295 MEM(escaped = talloc_array(vb,
char, vb->vb_length * 3 + 1));
302 if (len == vb->vb_length) {
328 }
while (*from && (*from != quote));
330 if (*from != quote)
return -1;
350 while (*from && (*from != quote)) {
359 if (*from != quote)
return -1;
383 if (sublen < 0)
return sublen;
402 if (from[1] ==
'{') {
407 if (sublen < 0)
return sublen;
433 if (*then != now->tv_sec) {
457 pps =
USEC - now->tv_usec;
480 int max_argc,
char const *argv[],
bool can_fail,
481 size_t argv_buflen,
char *argv_buf)
488 size_t len = strlen(cmd);
490 if (len > (argv_buflen - 1)) {
498 if ((len > 0) && (cmd[len - 1] ==
'\\')) {
499 fr_strerror_const(
"Expansion string ends with a trailing backslash - invalid escape sequence");
503 strlcpy(argv_buf, cmd, argv_buflen);
519 if (argc >= (max_argc - 1))
break;
524 while (*from && (*from !=
' ') && (*from !=
'\t')) {
525 if (to >= argv_buf + argv_buflen - 1) {
543 if (from[1] ==
'{') {
559 if (from[1] ==
' ') from++;
581 left = argv_buf + argv_buflen - to;
582 for (i = 0; i < argc; i++) {
588 if (strchr(argv[i],
'%') == NULL)
continue;
590 if (!request)
continue;
592 sublen =
xlat_eval(to, left - 1, request, argv[i], NULL, NULL);
625static bool doing_setuid =
false;
626static uid_t suid_down_uid = (uid_t)-1;
640# if defined(HAVE_SETRESUID) && defined (HAVE_GETRESUID)
643 uid_t ruid, euid, suid;
645 if (getresuid(&ruid, &euid, &suid) < 0) {
646 ERROR(
"Failed getting saved UID's");
650 if (setresuid(-1, suid, -1) < 0) {
651 ERROR(
"Failed switching to privileged user");
655 if (geteuid() != suid) {
656 ERROR(
"Switched to unknown UID");
663 if (!doing_setuid)
return;
665 if (setresuid(-1, suid_down_uid, geteuid()) < 0) {
666 struct passwd *passwd;
675 if (geteuid() != suid_down_uid) {
676 ERROR(
"Failed switching uid: UID is incorrect");
685 if (!doing_setuid)
return;
687 if (setresuid(suid_down_uid, suid_down_uid, suid_down_uid) < 0) {
688 struct passwd *passwd;
697 if (geteuid() != suid_down_uid) {
698 ERROR(
"Switched to unknown uid");
708 ERROR(
"Failed disabling CAP_SUID");
716 ERROR(
"Failed disabling CAP_SGID");
731 if (!doing_setuid)
return;
733 if (seteuid(0) < 0) {
742 if (!doing_setuid)
return;
744 if (geteuid() == suid_down_uid)
return;
746 if (seteuid(suid_down_uid) < 0) {
747 struct passwd *passwd;
761 if (!doing_setuid)
return;
766 if (getuid() == suid_down_uid)
return;
772 if (geteuid() == suid_down_uid) {
776 if (setuid(suid_down_uid) < 0) {
777 struct passwd *passwd;
831 if (seteuid(uid) < 0) {
832 int sete_errno = errno;
833 struct passwd *passwd;
853 if (setegid(gid) < 0) {
854 int sete_errno = errno;
#define fr_base16_encode(_out, _in)
#define FALL_THROUGH
clang 10 doesn't recognised the FALL-THROUGH comment anymore
#define fr_cap_disable(_x, _y)
#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)
int rad_filename_box_escape(fr_value_box_t *vb, UNUSED void *uxtc)
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)
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_OUT(_start, _len_or_end)
#define fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
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 ** out