25 RCSID(
"$Id: 1435f94150996de950a092d0d3fb0c28f7ba2dd0 $")
27 #include <freeradius-devel/util/debug.h>
28 #include <freeradius-devel/server/request.h>
29 #include <freeradius-devel/server/util.h>
30 #include <freeradius-devel/server/exec_legacy.h>
31 #include <freeradius-devel/server/exec_priv.h>
33 #define MAX_ARGV (256)
36 size_t envlen,
bool shell_escape)
52 vp && (i < envlen - 1);
63 for (p =
buffer; *p !=
'='; p++) {
66 }
else if (isalpha((
uint8_t) *p)) {
84 vp && (i < (envlen - 1));
87 memcpy(&envp[i++], &
vp->vp_strvalue,
sizeof(*envp));
114 devnull = open(
"/dev/null", O_RDWR);
116 fprintf(stderr,
"Failed opening /dev/null: %s\n",
fr_syserror(errno));
132 if (stdin_pipe[1] >= 0) {
133 close(stdin_pipe[1]);
134 dup2(stdin_pipe[0], STDIN_FILENO);
191 execve(argv[0], argv, envp);
192 printf(
"Failed to execute \"%s\": %s", argv[0],
fr_syserror(errno));
228 char const *cmd,
request_t *request,
bool exec_wait,
231 int stdin_pipe[2] = {-1, -1};
238 char *argv[
MAX_ARGV], **argv_start = argv;
240 #define MAX_ENVP 1024
249 memcpy(&argv_p, &argv_start,
sizeof(argv_p));
257 for (i = 0; i < argc; i++)
DEBUG3(
"arg[%d] %s", i, argv[i]);
265 if (pipe(stdin_pipe) != 0) {
275 close(stdin_pipe[0]);
276 close(stdin_pipe[1]);
293 MEM(envp = talloc_zero_array(request,
char *,
MAX_ENVP));
312 if (exec_wait)
goto error;
325 *stdin_fd = stdin_pipe[1];
326 close(stdin_pipe[0]);
389 DEBUG(
"Child PID %u is taking too much time: forcing failure and killing child.", pid);
400 if (errno == EINTR)
continue;
409 status = read(fd, answer +
done, left);
415 status = read(fd, answer +
done, 1);
432 if (errno == EINTR) {
446 if (left <= 0)
break;
450 while ((
done > 0) && (answer[
done - 1] ==
'\n')) {
451 answer[--
done] =
'\0';
504 RERROR(
"Failed to read from child output");
530 child_pid =
waitpid(pid, &status, 0);
531 if (child_pid == 0) {
532 RERROR(
"Timeout waiting for child");
537 if (child_pid == pid) {
541 RERROR(
"Program returned code (%d) and output \"%pV\"", status,
544 RDEBUG2(
"Program returned code (%d) and output \"%pV\"", status,
static int const char char buffer[256]
#define fr_atexit_thread_local_disarm_all(...)
#define NEVER_RETURNS
Should be placed before the function return type.
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
static fr_time_delta_t timeout
fr_dict_attr_t const * fr_dict_root(fr_dict_t const *dict)
Return the root attribute of a dictionary.
fr_dict_t const * fr_dict_internal(void)
fr_dict_attr_t const * fr_dict_attr_child_by_num(fr_dict_attr_t const *parent, unsigned int attr)
Check if a child attribute exists in a parent using an attribute number.
#define fr_event_pid_wait(...)
int radius_exec_program_legacy(char *out, size_t outlen, request_t *request, char const *cmd, fr_pair_list_t *input_pairs, bool exec_wait, bool shell_escape, fr_time_delta_t timeout)
Execute a program.
pid_t radius_start_program_legacy(int *stdin_fd, int *stdout_fd, int *stderr_fd, char const *cmd, request_t *request, bool exec_wait, fr_pair_list_t *input_pairs, bool shell_escape)
Start a process.
static NEVER_RETURNS void exec_child_legacy(request_t *request, char **argv, char **envp, bool exec_wait, int stdin_pipe[static 2], int stdout_pipe[static 2], int stderr_pipe[static 2])
int radius_readfrom_program_legacy(int fd, pid_t pid, fr_time_delta_t timeout, char *answer, int left)
Read from the child process.
static void exec_pair_to_env_legacy(request_t *request, fr_pair_list_t *input_pairs, char **envp, size_t envlen, bool shell_escape)
fr_event_list_t * unlang_interpret_event_list(request_t *request)
Get the event list for the current interpreter.
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
#define RPEDEBUG(fmt,...)
#define DEBUG_ENABLED3
True if global debug level 1-3 messages are enabled.
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.
waitpid(reap->pid_ev->pid, &status, 0)
Stores all information relating to an event list.
static FILE * devnull
File handle for /dev/null.
static int stdout_fd
The original unmolested stdout file descriptor.
static int stdout_pipe[2]
Pipe we use to transport stdout data.
static int stderr_pipe[2]
Pipe we use to transport stderr data.
static int stderr_fd
The original unmolested stderr file descriptor.
int fr_nonblock(UNUSED int fd)
#define WIFEXITED(stat_val)
#define WEXITSTATUS(stat_val)
#define FR_SBUFF_OUT(_start, _len_or_end)
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
#define fr_time()
Allow us to arbitrarily manipulate time.
size_t strlcpy(char *dst, char const *src, size_t siz)
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
static int64_t fr_time_delta_unwrap(fr_time_delta_t time)
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_delta_to_timeval(_delta)
Convert a delta to a timeval.
static fr_time_delta_t fr_time_delta_sub(fr_time_delta_t a, fr_time_delta_t b)
#define fr_time_delta_gteq(_a, _b)
#define fr_time_sub(_a, _b)
Subtract one time from another.
A time delta, a difference in time measured in nanoseconds.
static fr_event_list_t * el
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.
ssize_t fr_pair_print_value_quoted(fr_sbuff_t *out, fr_pair_t const *vp, fr_token_t quote)
Print the value of an attribute to a string.
#define fr_box_strvalue_len(_val, _len)
static size_t char ** out