23RCSID(
"$Id: 82a1aa7c13634532bd6d9bd7ddbd38ebae63b3c8 $")
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>
51 struct sigaction act, oact;
53 memset(&act, 0,
sizeof(act));
54 act.sa_handler = func;
55 sigemptyset(&act.sa_mask);
58 act.sa_flags |= SA_INTERRUPT;
60 if (sigaction(signo, &act, &oact) < 0)
62 return oact.sa_handler;
149 if ((q[0] ==
'.') && (q[1] ==
'.') &&
165 if (vb->vb_length == 0)
return 0;
172 MEM(escaped = talloc_array(vb,
char, vb->vb_length + 1));
207 size_t freespace = outlen;
209 while (*
in !=
'\0') {
217 if (freespace <= (utf8_len * 3))
break;
233 freespace -= (utf8_len * 3);
234 out += (utf8_len * 3);
243 if (((*
in >=
'A') && (*
in <=
'Z')) ||
244 ((*
in >=
'a') && (*
in <=
'z')) ||
245 ((*
in >=
'0') && (*
in <=
'9')) ||
247 if (freespace <= 1)
break;
253 if (freespace <= 2)
break;
278 return outlen - freespace;
286 if (vb->vb_length == 0)
return 0;
294 MEM(escaped = talloc_array(vb,
char, vb->vb_length * 3 + 1));
301 if (len == vb->vb_length) {
323 char const *p, *end =
in +
inlen;
324 size_t freespace = outlen;
326 for (p =
in; p < end; p++) {
327 if (freespace <= 1)
break;
329 if (((*p >=
'A') && (*p <=
'Z')) ||
330 ((*p >=
'a') && (*p <=
'z')) ||
331 ((*p >=
'0') && (*p <=
'9')) ||
343 if ((end - p) < 2)
return in - p;
355 if ((end - p) < 3)
return in - p;
372 return outlen - freespace;
383char *
rad_ajoin(TALLOC_CTX *ctx,
char const **argv,
int argc,
char c)
387 size_t total = 0, freespace;
393 for (i = 0; i < argc; i++) total += (strlen(argv[i]) + ((c ==
'\0') ? 0 : 1));
396 return talloc_zero_array(ctx,
char, 1);
399 if (c ==
'\0') total++;
402 buff = p = talloc_array(ctx,
char, total);
403 for (i = 0; i < argc; i++) {
406 len =
strlcpy(p, argv[i], freespace);
433 }
while (*from && (*from != quote));
435 if (*from != quote)
return -1;
455 while (*from && (*from != quote)) {
464 if (*from != quote)
return -1;
488 if (sublen < 0)
return sublen;
507 if (from[1] ==
'{') {
512 if (sublen < 0)
return sublen;
538 if (*then != now->tv_sec) {
562 pps =
USEC - now->tv_usec;
585 int max_argc,
char const *argv[],
bool can_fail,
586 size_t argv_buflen,
char *argv_buf)
594 if (strlen(cmd) > (argv_buflen - 1)) {
602 if (cmd[strlen(cmd) - 1] ==
'\\') {
603 fr_strerror_const(
"Expansion string ends with a trailing backslash - invalid escape sequence");
607 strlcpy(argv_buf, cmd, argv_buflen);
623 if (argc >= (max_argc - 1))
break;
628 while (*from && (*from !=
' ') && (*from !=
'\t')) {
629 if (to >= argv_buf + argv_buflen - 1) {
647 if (from[1] ==
'{') {
663 if (from[1] ==
' ') from++;
685 left = argv_buf + argv_buflen - to;
686 for (i = 0; i < argc; i++) {
692 if (strchr(argv[i],
'%') == NULL)
continue;
694 if (!request)
continue;
696 sublen =
xlat_eval(to, left - 1, request, argv[i], NULL, NULL);
729static bool doing_setuid =
false;
730static uid_t suid_down_uid = (uid_t)-1;
744# if defined(HAVE_SETRESUID) && defined (HAVE_GETRESUID)
747 uid_t ruid, euid, suid;
749 if (getresuid(&ruid, &euid, &suid) < 0) {
750 ERROR(
"Failed getting saved UID's");
754 if (setresuid(-1, suid, -1) < 0) {
755 ERROR(
"Failed switching to privileged user");
759 if (geteuid() != suid) {
760 ERROR(
"Switched to unknown UID");
767 if (!doing_setuid)
return;
769 if (setresuid(-1, suid_down_uid, geteuid()) < 0) {
770 struct passwd *passwd;
779 if (geteuid() != suid_down_uid) {
780 ERROR(
"Failed switching uid: UID is incorrect");
789 if (!doing_setuid)
return;
791 if (setresuid(suid_down_uid, suid_down_uid, suid_down_uid) < 0) {
792 struct passwd *passwd;
801 if (geteuid() != suid_down_uid) {
802 ERROR(
"Switched to unknown uid");
816 if (!doing_setuid)
return;
818 if (seteuid(0) < 0) {
827 if (!doing_setuid)
return;
829 if (geteuid() == suid_down_uid)
return;
831 if (seteuid(suid_down_uid) < 0) {
832 struct passwd *passwd;
846 if (!doing_setuid)
return;
851 if (getuid() == suid_down_uid)
return;
857 if (geteuid() == suid_down_uid) {
861 if (setuid(suid_down_uid) < 0) {
862 struct passwd *passwd;
916 if (seteuid(uid) < 0) {
917 int sete_errno = errno;
918 struct passwd *passwd;
938 if (setegid(gid) < 0) {
939 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)
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]
#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 fr_sbuff_t size_t inlen
static size_t char ** out