23 RCSID(
"$Id: 52b111adacb297a27e1dc27dd37770b4c74bedf2 $")
25 #include <freeradius-devel/server/base.h>
26 #include <freeradius-devel/server/stats.h>
27 #include <freeradius-devel/server/util.h>
29 #include <freeradius-devel/util/debug.h>
30 #include <freeradius-devel/util/base16.h>
31 #include <freeradius-devel/util/misc.h>
32 #include <freeradius-devel/util/perm.h>
33 #include <freeradius-devel/util/syserror.h>
35 #include <freeradius-devel/unlang/xlat.h>
58 struct sigaction act, oact;
60 memset(&act, 0,
sizeof(act));
61 act.sa_handler = func;
62 sigemptyset(&act.sa_mask);
65 act.sa_flags |= SA_INTERRUPT;
67 if (sigaction(signo, &act, &oact) < 0)
69 return oact.sa_handler;
100 size_t left = outlen;
156 if ((q[0] ==
'.') && (q[1] ==
'.') &&
171 fr_value_box_entry_t entry;
173 if (vb->vb_length == 0)
return 0;
179 MEM(escaped = talloc_array(vb,
char, vb->vb_length + 1));
218 size_t freespace = outlen;
220 while (*
in !=
'\0') {
228 if (freespace <= (utf8_len * 3))
break;
244 freespace -= (utf8_len * 3);
245 out += (utf8_len * 3);
254 if (((*
in >=
'A') && (*
in <=
'Z')) ||
255 ((*
in >=
'a') && (*
in <=
'z')) ||
256 ((*
in >=
'0') && (*
in <=
'9')) ||
258 if (freespace <= 1)
break;
264 if (freespace <= 2)
break;
289 return outlen - freespace;
296 fr_value_box_entry_t entry;
298 if (vb->vb_length == 0)
return 0;
305 MEM(escaped = talloc_array(vb,
char, vb->vb_length * 3 + 1));
312 if (len == vb->vb_length) {
338 char const *p, *end =
in +
inlen;
339 size_t freespace = outlen;
341 for (p =
in; p < end; p++) {
342 if (freespace <= 1)
break;
344 if (((*p >=
'A') && (*p <=
'Z')) ||
345 ((*p >=
'a') && (*p <=
'z')) ||
346 ((*p >=
'0') && (*p <=
'9')) ||
358 if ((end - p) < 2)
return in - p;
370 if ((end - p) < 3)
return in - p;
387 return outlen - freespace;
398 char *
rad_ajoin(TALLOC_CTX *ctx,
char const **argv,
int argc,
char c)
402 size_t total = 0, freespace;
408 for (i = 0; i < argc; i++) total += (strlen(argv[i]) + ((c ==
'\0') ? 0 : 1));
411 return talloc_zero_array(ctx,
char, 1);
414 if (c ==
'\0') total++;
417 buff = p = talloc_array(ctx,
char, total);
418 for (i = 0; i < argc; i++) {
421 len =
strlcpy(p, argv[i], freespace);
448 }
while (*from && (*from != quote));
450 if (*from != quote)
return -1;
470 while (*from && (*from != quote)) {
479 if (*from != quote)
return -1;
503 if (sublen < 0)
return sublen;
522 if (from[1] ==
'{') {
527 if (sublen < 0)
return sublen;
553 if (*then != now->tv_sec) {
577 pps =
USEC - now->tv_usec;
600 int max_argc,
char const *argv[],
bool can_fail,
601 size_t argv_buflen,
char *argv_buf)
609 if (strlen(cmd) > (argv_buflen - 1)) {
617 if (cmd[strlen(cmd) - 1] ==
'\\') {
618 fr_strerror_const(
"Expansion string ends with a trailing backslash - invalid escape sequence");
622 strlcpy(argv_buf, cmd, argv_buflen);
638 if (argc >= (max_argc - 1))
break;
643 while (*from && (*from !=
' ') && (*from !=
'\t')) {
644 if (to >= argv_buf + argv_buflen - 1) {
662 if (from[1] ==
'{') {
678 if (from[1] ==
' ') from++;
700 left = argv_buf + argv_buflen - to;
701 for (i = 0; i < argc; i++) {
707 if (strchr(argv[i],
'%') == NULL)
continue;
709 if (!request)
continue;
711 sublen =
xlat_eval(to, left - 1, request, argv[i], NULL, NULL);
744 static bool doing_setuid =
false;
745 static uid_t suid_down_uid = (uid_t)-1;
759 # if defined(HAVE_SETRESUID) && defined (HAVE_GETRESUID)
762 uid_t ruid, euid, suid;
764 if (getresuid(&ruid, &euid, &suid) < 0) {
765 ERROR(
"Failed getting saved UID's");
769 if (setresuid(-1, suid, -1) < 0) {
770 ERROR(
"Failed switching to privileged user");
774 if (geteuid() != suid) {
775 ERROR(
"Switched to unknown UID");
782 if (!doing_setuid)
return;
784 if (setresuid(-1, suid_down_uid, geteuid()) < 0) {
785 struct passwd *passwd;
794 if (geteuid() != suid_down_uid) {
795 ERROR(
"Failed switching uid: UID is incorrect");
804 if (!doing_setuid)
return;
806 if (setresuid(suid_down_uid, suid_down_uid, suid_down_uid) < 0) {
807 struct passwd *passwd;
816 if (geteuid() != suid_down_uid) {
817 ERROR(
"Switched to unknown uid");
831 if (!doing_setuid)
return;
833 if (seteuid(0) < 0) {
842 if (!doing_setuid)
return;
844 if (geteuid() == suid_down_uid)
return;
846 if (seteuid(suid_down_uid) < 0) {
847 struct passwd *passwd;
861 if (!doing_setuid)
return;
866 if (getuid() == suid_down_uid)
return;
872 if (geteuid() == suid_down_uid) {
876 if (setuid(suid_down_uid) < 0) {
877 struct passwd *passwd;
931 if (seteuid(uid) < 0) {
932 int sete_errno = errno;
933 struct passwd *passwd;
953 if (setegid(gid) < 0) {
954 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)
int rad_filename_box_escape(fr_value_box_t *vb, UNUSED void *uxtc)
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
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)
Signals that can be sent to a request.
static char buff[sizeof("18446744073709551615")+3]
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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_clear_value(fr_value_box_t *data)
Clear/free any existing value.
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
static size_t char fr_sbuff_t size_t inlen
uintptr_t fr_value_box_safe_for_t
Escaping that's been applied to a value box.
static size_t char ** out