source: trunk/src/sh_extern.c@ 211

Last change on this file since 211 was 211, checked in by katerina, 16 years ago

Allow shell expansion for cofiguration file values (ticket #137).

File size: 34.9 KB
RevLine 
[1]1/* SAMHAIN file system integrity testing */
2/* Copyright (C) 2000,2004 Rainer Wichmann */
3/* */
4/* This program is free software; you can redistribute it */
5/* and/or modify */
6/* it under the terms of the GNU General Public License as */
7/* published by */
8/* the Free Software Foundation; either version 2 of the License, or */
9/* (at your option) any later version. */
10/* */
11/* This program is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14/* GNU General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU General Public License */
17/* along with this program; if not, write to the Free Software */
18/* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20
21#include "config_xor.h"
22
23
24#include <stdio.h>
25#include <string.h>
26#ifdef HAVE_MEMORY_H
27#include <memory.h>
28#endif
29
30/* replace #if 0 by #if 1 and set an appropriate path in front of '/pdbg.'
31 * for debugging
32 */
[211]33#if 1
34#define PDGBFILE "/home/rainer/PROJECTS/samhain/devel/pdbg."
[1]35#endif
36
37
38#if defined(PDGBFILE)
39static FILE * pdbg = NULL;
40static FILE * pdbgc = NULL;
41#define PDBG_OPEN if (pdbg == NULL) pdbg = fopen(PDGBFILE"main", "a")
42#define PDBG_CLOSE fclose (pdbg); pdbg = NULL
43#define PDBG(arg) fprintf(pdbg, "PDBG: step %d\n", arg); fflush(pdbg)
44#define PDBG_D(arg) fprintf(pdbg, "PDBG: %d\n", arg); fflush(pdbg)
45#define PDBG_S(arg) fprintf(pdbg, "PDBG: %s\n", arg); fflush(pdbg)
46
47#define PDBGC_OPEN if (pdbgc == NULL) pdbgc = fopen(PDGBFILE"child", "a")
48#define PDBGC_CLOSE fclose (pdbgc); pdbgc = NULL
49#define PDBGC(arg) fprintf(pdbgc, "PDBGC: step %d\n", arg); fflush(pdbgc)
50#define PDBGC_D(arg) fprintf(pdbgc, "PDBGC: %d\n", arg); fflush(pdbgc)
51#define PDBGC_S(arg) fprintf(pdbgc, "PDBGC: %s\n", arg); fflush(pdbgc)
52#else
53#define PDBG_OPEN
54#define PDBG_CLOSE
55#define PDBG(arg)
56#define PDBG_D(arg)
57#define PDBG_S(arg)
58#define PDBGC_OPEN
59#define PDBGC_CLOSE
60#define PDBGC(arg)
61#define PDBGC_D(arg)
62#define PDBGC_S(arg)
63#endif
64
65
66#include <stdlib.h>
67#include <pwd.h>
68#include <unistd.h>
69#include <fcntl.h>
70#include <signal.h>
71#include <sys/stat.h>
72#include <sys/types.h>
73#include <errno.h>
74#include <sys/wait.h>
75
76#if TIME_WITH_SYS_TIME
77#include <sys/time.h>
78#include <time.h>
79#else
80#if HAVE_SYS_TIME_H
81#include <sys/time.h>
82#else
83#include <time.h>
84#endif
85#endif
86
87
88#include "samhain.h"
89#include "sh_utils.h"
90#include "sh_unix.h"
91#include "sh_tiger.h"
92#include "sh_extern.h"
93#include "sh_calls.h"
94#define SH_NEED_PWD_GRP 1
95#include "sh_static.h"
96
97
98#undef FIL__
99#define FIL__ _("sh_extern.c")
100
101extern int get_the_fd (SL_TICKET ticket);
102
103/*
104 * -- generic safe popen
105 */
106
107int sh_ext_popen (sh_tas_t * task)
108{
109 long status = 0;
110 int flags;
111 char * tmp;
112 char * tmp2;
113 int errnum;
114 int pipedes[2];
115 FILE * outf = NULL;
116 char * envp[1];
[29]117 char * argp[2];
[1]118
119 char * errfile;
[132]120 char errbuf[SH_ERRBUF_SIZE];
[1]121
122 static int some_error = 0;
123
124#if defined (__linux__)
125 SL_TICKET fd = -1;
126 char pname[128];
127 int pfd = -1;
128#endif
[102]129
[1]130 SL_ENTER(_("sh_ext_popen"));
131
132 /* Linux, HP-UX and FreeBSD will happily accept envp = argp = NULL
133 * Solaris (and probably some other Unices)
134 * needs a valid *envp[] with envp[0] = NULL;
135 * and similarly for argp
[29]136 * OpenBSD finally needs non-null argp[0] ...
[1]137 */
[29]138 argp[0] = task->command;
139 argp[1] = NULL;
[1]140 envp[0] = NULL;
141
142 /*
143 * -- check whether path is trustworthy
144 */
[169]145 status = sl_trustfile(task->command, NULL, NULL);
146#if 0
[1]147 if ((uid_t) -1 != task->trusted_users[0])
148 {
149 status = sl_trustfile(task->command, task->trusted_users, NULL);
150 }
[169]151#endif
[1]152
153 PDBG_OPEN;
154 PDBG_D( (int) status);
155
156 if ( SL_ENONE != status)
157 {
158 PDBG_S("SL_ENONE != status");
159 if (some_error == 0)
160 {
161 tmp = sh_util_safe_name (task->command);
162 errfile = sl_trust_errfile();
163 if (errfile[0] != '\0')
164 {
165 tmp2 = sh_util_safe_name (sl_trust_errfile());
166 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_TRUST2,
167 sl_error_string((int)status), tmp, tmp2);
168 SH_FREE(tmp2);
169 }
170 else
171 {
172 sh_error_handle((-1), FIL__, __LINE__, status, MSG_E_TRUST1,
173 sl_error_string((int)status), tmp);
174 }
175 SH_FREE(tmp);
176 }
177 some_error = 1;
178 SL_RETURN ((-1), _("sh_ext_popen"));
179 }
180
181 PDBG(1);
182
183 /*
184 * -- check whether the checksum is correct; with linux emulate fdexec
185 */
186#if !defined(__linux__) && !defined(SL_DEBUG)
187 if (task->checksum[0] != '\0')
188 {
[133]189 char hashbuf[KEYBUF_SIZE];
[1]190 PDBG_S("checksum test");
191 if (0 != sl_strcmp(task->checksum,
[160]192 sh_tiger_hash (task->command, TIGER_FILE, TIGER_NOLIM,
[133]193 hashbuf, sizeof(hashbuf))
194 )
[1]195 )
196 {
197 PDBG_S("checksum mismatch");
198 if (some_error == 0)
199 {
200 tmp = sh_util_safe_name (task->command);
201 sh_error_handle((-1), FIL__, __LINE__, 0, MSG_E_HASH, tmp);
202 SH_FREE(tmp);
203 }
204 some_error = 1;
205 SL_RETURN ((-1), _("sh_ext_popen"));
206 }
207 }
208#endif
209
210 some_error = 0;
211
212 PDBG(2);
213
214 /*
215 * -- Create the pipe
216 */
217 if (aud_pipe(FIL__, __LINE__, pipedes) < 0)
218 {
219 PDBG_S("pipe() failure");
220 errnum = errno;
221 sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_E_SUBGEN,
[132]222 sh_error_message(errnum, errbuf, sizeof(errbuf)), _("pipe"));
[1]223 SL_RETURN ((-1), _("sh_ext_popen"));
224 }
225
226 PDBG(3);
[102]227
[1]228 /*
[102]229 * -- Flush streams and fork
[1]230 */
[102]231 fflush (NULL);
232
[1]233 task->pid = aud_fork(FIL__, __LINE__);
234
235 if (task->pid == (pid_t) - 1)
236 {
237 PDBG_S("fork() failure");
238 /*@-usedef@*/
239 (void) close(pipedes[0]);
240 (void) close(pipedes[1]);
241 /*@+usedef@*/
242 errnum = errno;
243 sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_E_SUBGEN,
[132]244 sh_error_message(errnum, errbuf, sizeof(errbuf)), _("fork"));
[1]245 SL_RETURN ((-1), _("sh_ext_popen"));
246 }
247
248 PDBG(4);
249
250 if (task->pid == (pid_t) 0)
251 {
252 /*
253 * -- fork again, if requested
254 */
255 if (S_TRUE == task->fork_twice)
256 {
257 task->pid = aud_fork(FIL__, __LINE__);
258
259 if (task->pid == (pid_t) - 1)
260 {
261 aud__exit (FIL__, __LINE__, EXIT_FAILURE);
262 }
263 }
264
265 if (task->pid == (pid_t) 0)
266 {
267 PDBGC_OPEN;
268 PDBGC(1);
269
270 /*
271 * -- grandchild - make write side of the pipe stdin
272 */
273 if (task->rw == 'w')
274 {
275 if (retry_aud_dup2(FIL__, __LINE__,
276 pipedes[STDIN_FILENO], STDIN_FILENO) < 0)
277 aud__exit(FIL__, __LINE__,EXIT_FAILURE);
278 }
279 else
280 {
281 if (retry_aud_dup2(FIL__, __LINE__,
282 pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
283 aud__exit(FIL__, __LINE__,EXIT_FAILURE);
284 }
285 PDBGC(2);
286
287
288 /* close the pipe descriptors
289 */
290 (void) close (pipedes[STDIN_FILENO]);
291 (void) close (pipedes[STDOUT_FILENO]);
292
293 /* don't leak file descriptors
294 */
295#if !defined(PDGBFILE)
[174]296 sh_unix_closeall (3, task->com_fd, SL_TRUE); /* in child process */
[1]297#endif
298
299 /* drop root privileges, if possible && requested
300 */
301 if (task->privileged == 0 && 0 == getuid())
302 {
303 PDBGC_S("privileged");
304
305 /* zero priv info
306 */
307 memset(skey, 0, sizeof(sh_key_t));
308
309 (void) aud_setgid(FIL__, __LINE__,(gid_t) task->run_user_gid);
310 (void) aud_setuid(FIL__, __LINE__,(uid_t) task->run_user_uid);
311 /* make sure we cannot get root again
312 */
313 if (aud_setuid(FIL__, __LINE__,0) >= 0)
314 aud__exit(FIL__, __LINE__,EXIT_FAILURE);
315 }
316
317 PDBGC(3);
318 (void) fflush(NULL);
319
320 if (task->rw == 'w')
321 {
322 PDBGC_S("w");
323 (void) fcntl (STDOUT_FILENO, F_SETFD, FD_CLOEXEC);
324 (void) fcntl (STDERR_FILENO, F_SETFD, FD_CLOEXEC);
325 /*
326 freopen(_("/dev/null"), "r+", stderr);
327 freopen(_("/dev/null"), "r+", stdout);
328 */
329 }
330 else
331 {
332 PDBGC_S("r");
333 (void) retry_aud_dup2 (FIL__, __LINE__,
334 STDOUT_FILENO, STDERR_FILENO);
335 (void) fcntl (STDIN_FILENO, F_SETFD, FD_CLOEXEC);
336 /*
337 freopen(_("/dev/null"), "r+", stdin);
338 */
339 }
340
341 PDBGC(4);
342
343
344#if defined(__linux__)
345 /*
346 * -- emulate an fdexec with checksum testing
347 */
348 if (task->checksum[0] != '\0')
349 {
350 PDBGC_S("fexecve");
351 if (task->com_fd != (-1))
352 {
353 pfd = retry_aud_dup(FIL__, __LINE__, task->com_fd);
354 if (pfd < 0)
355 {
356 PDBGC_S("fexecve: dup2 failed");
357 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
358 }
359 }
360 else
361 {
[133]362 char hashbuf[KEYBUF_SIZE];
363
[1]364 fd =
365 sl_open_read(task->command,
366 task->privileged==0 ? SL_NOPRIV : SL_YESPRIV);
[133]367
[1]368 if (0 != sl_strcmp(task->checksum,
369 sh_tiger_hash (task->command,
[160]370 fd, TIGER_NOLIM, hashbuf, sizeof(hashbuf))))
[1]371 {
372 PDBGC_S("fexecve: checksum mismatch");
373 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
374 }
375 pfd = get_the_fd(fd);
376 }
377
378 PDBGC(5);
[22]379 sl_snprintf(pname, sizeof(pname), _("/proc/self/fd/%d"), pfd);
380 if (access(pname, R_OK|X_OK) == 0) /* flawfinder: ignore */
[1]381 {
382 PDBGC(6);
383 PDBGC_CLOSE;
384 fcntl (pfd, F_SETFD, FD_CLOEXEC);
385 retry_aud_execve (FIL__, __LINE__,
386 pname,
387 (task->argc == 0) ? NULL : task->argv,
388 (task->envc == 0) ? NULL : task->envv
389 );
390
391 errnum = errno;
392 PDBGC_OPEN;
393 PDBGC_S(strerror(errnum));
394 PDBGC_S(task->command);
395 PDBGC_S("fexecve: failed");
396 PDBGC_CLOSE;
397 /* failed
398 */
399 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
400 }
401 PDBGC_S("fexecve: not working");
402 /*
403 * procfs not working, go ahead; checksum is tested already
404 */
405 if (fd != -1)
406 sl_close(fd);
407 else if (pfd != -1)
408 close(fd);
409 }
410#endif
411
412 PDBGC_S(" -- non fexecve --");
413 /*
414 * -- execute path if executable
415 */
[22]416 if (0 == access(task->command, R_OK|X_OK)) /* flawfinder: ignore */
[1]417 {
418 PDBGC(5);
419 PDBGC_CLOSE;
420 (void) retry_aud_execve (FIL__, __LINE__,
421 task->command,
422 (task->argc == 0) ? argp : task->argv,
423 (task->envc == 0) ? envp : task->envv
424 );
425 }
426 errnum = errno;
427 PDBGC_OPEN;
428 PDBGC_S(strerror(errnum));
429 PDBGC_S(task->command);
430 PDBGC_S("execve: failed");
431 PDBGC_CLOSE;
432 /* failed
433 */
434 aud__exit(FIL__, __LINE__, EXIT_FAILURE);
435 }
436 /*
437 * if we have forked twice, this is parent::detached_subprocess
438 */
439 if (S_TRUE == task->fork_twice)
440 {
441 aud__exit (FIL__, __LINE__, 0);
442 }
443 }
444
445
446 /*
447 * -- parent; task->pid is child pid; exit status is status of
448 * grandchild if exited
449 */
450 if (S_TRUE == task->fork_twice)
451 {
452 (void) waitpid (task->pid, NULL, 0);
453 }
454
455 PDBG(5);
456 /* open an output stream on top of the write side of the pipe
457 */
458 if (task->rw == 'w')
459 {
460 PDBG_S("is w");
461 (void) close (pipedes[STDIN_FILENO]);
462 (void) retry_fcntl (FIL__, __LINE__, pipedes[STDOUT_FILENO],
463 F_SETFD, FD_CLOEXEC);
464 outf = fdopen (pipedes[STDOUT_FILENO], "w");
465 }
466 else
467 {
468 PDBG_S("is r");
469 (void) close (pipedes[STDOUT_FILENO]);
470 (void) retry_fcntl (FIL__, __LINE__, pipedes[STDIN_FILENO],
471 F_SETFD, FD_CLOEXEC);
472 outf = fdopen (pipedes[STDIN_FILENO], "r");
473 }
474
475 if (outf == NULL)
476 {
477 errnum = errno;
478 PDBG_S("outf == NULL");
479 tmp = sh_util_safe_name (task->command);
480
481 if (task->privileged == 0 && 0 == getuid())
482 sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_NOEXEC,
483 (UID_CAST) task->run_user_uid, tmp);
484 else
485 sh_error_handle((-1), FIL__, __LINE__, errnum, MSG_NOEXEC,
486 (UID_CAST) getuid(), tmp);
487
488 SH_FREE(tmp);
489
490 (void) aud_kill (FIL__, __LINE__, task->pid, SIGKILL);
491 (void) close (pipedes[STDOUT_FILENO]);
492 (void) close (pipedes[STDIN_FILENO]);
493 (void) waitpid (task->pid, NULL, 0);
494 task->pid = 0;
495
496 SL_RETURN ((-1), _("sh_ext_popen"));
497 }
498
499 if (task->rw == 'w')
500 task->pipeFD = pipedes[STDOUT_FILENO];
501 else
502 task->pipeFD = pipedes[STDIN_FILENO];
503
504 PDBG_D(task->pipeFD);
505
506 task->pipeTI = sl_make_ticket(task->pipeFD, _("pipe"));
507
508 flags = (int) retry_fcntl (FIL__, __LINE__, task->pipeFD, F_GETFL, 0);
509 if (flags != (-1))
510 (void) retry_fcntl (FIL__, __LINE__, task->pipeFD,
511 F_SETFL, flags|O_NONBLOCK);
512 task->pipe = outf;
513
514 PDBG_S("return from popen");
515 PDBG_CLOSE;
516
517 SL_RETURN (0, _("sh_ext_popen"));
518}
519
520/*
521 * -- close the pipe
522 */
523extern int flag_err_debug;
524
525int sh_ext_pclose (sh_tas_t * task)
526{
527 int status = 0;
528 int retry = 0;
529 pid_t retval;
530 char infomsg[256];
531
532 SL_ENTER(_("sh_ext_pclose"));
533
[211]534 PDBG_OPEN;
[1]535 PDBG_S(" -> pclose");
536 (void) fflush(task->pipe);
537 (void) fclose(task->pipe);
538 if (!SL_ISERROR(task->pipeTI))
539 (void) sl_close(task->pipeTI);
540
541 task->pipe = NULL;
542 task->pipeFD = (-1);
543 task->pipeTI = SL_ETICKET;
544
545 if (S_FALSE == task->fork_twice)
546 {
547 infomsg[0] = '\0';
548
549 nochmal:
550 retval = waitpid(task->pid, &(task->exit_status), WNOHANG|WUNTRACED);
551 /*@-bufferoverflowhigh@*/
552 if (task->pid == retval)
553 {
[96]554#ifndef USE_UNO
[1]555 if (WIFEXITED(task->exit_status) != 0)
556 {
557 task->exit_status = WEXITSTATUS(task->exit_status);
558 if ((flag_err_debug == SL_TRUE) || (task->exit_status != 0))
[22]559 sl_snprintf(infomsg, sizeof(infomsg),
560 _("Subprocess exited normally with status %d"),
561 task->exit_status);
[1]562 }
563 else if (WIFSIGNALED(task->exit_status) != 0)
564 {
[22]565 sl_snprintf(infomsg, sizeof(infomsg),
566 _("Subprocess terminated by signal %d"),
567 WTERMSIG(task->exit_status));
[1]568 task->exit_status = EXIT_FAILURE;
569 }
570 else if (WIFSTOPPED(task->exit_status) != 0)
571 {
[22]572 sl_snprintf(infomsg, sizeof(infomsg),
573 _("Subprocess stopped by signal %d, killing"),
574 WSTOPSIG(task->exit_status));
[1]575 task->exit_status = EXIT_FAILURE;
576 (void) aud_kill (FIL__, __LINE__, task->pid, 9);
577 (void) retry_msleep (0, 30);
578 (void) waitpid (task->pid, NULL, WNOHANG|WUNTRACED);
579 }
580 else
581 {
[22]582 sl_snprintf(infomsg, sizeof(infomsg),
583 _("Subprocess exit status unknown"));
[1]584 task->exit_status = EXIT_FAILURE;
585 }
[96]586#else
587 task->exit_status = EXIT_FAILURE;
588#endif
[1]589 }
590 else if (0 == retval)
591 {
592 if (retry < 3)
593 {
594 ++retry;
595 (void) retry_msleep(0, (retry * 30));
596 goto nochmal;
597 }
598 (void) aud_kill (FIL__, __LINE__, task->pid, 9);
[22]599 sl_snprintf(infomsg, sizeof(infomsg),
600 _("Subprocess not yet exited, killing"));
[1]601 task->exit_status = EXIT_FAILURE;
602 (void) waitpid (task->pid, NULL, 0);
603 }
604 else
605 {
[22]606 sl_snprintf(infomsg, sizeof(infomsg),
607 _("Waitpid returned error %d\n"), errno);
[1]608 task->exit_status = EXIT_FAILURE;
609 }
610 /*@+bufferoverflowhigh@*/
611 status = task->exit_status;
612 if (flag_err_debug == SL_TRUE)
613 {
614 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, task->exit_status,
615 MSG_E_SUBGEN, infomsg, _("sh_ext_pclose"));
616 }
617 else if (status != 0)
618 {
619 sh_error_handle(SH_ERR_INFO, FIL__, __LINE__, task->exit_status,
620 MSG_E_SUBGEN, infomsg, _("sh_ext_pclose"));
621 }
622 }
623
624 task->pid = 0;
625 task->exit_status = 0;
626 PDBG_S(" <--");
627 PDBG_CLOSE;
628 SL_RETURN (status, _("sh_ext_pclose"));
629}
630
631void sh_ext_tas_init (sh_tas_t * tas)
632{
633 int i;
634
635 tas->command = NULL;
636 tas->argc = 0;
637 tas->envc = 0;
638 tas->checksum[0] = '\0';
639 tas->pipeFD = (-1);
640 tas->pipeTI = SL_ETICKET;
641 tas->pid = (pid_t) -1;
642 tas->privileged = 1;
643 tas->pipe = NULL;
644 tas->rw = 'w';
645 tas->exit_status = 0;
646 tas->fork_twice = S_TRUE;
647
648 for (i = 0; i < 32; ++i)
649 {
650 tas->argv[i] = NULL;
651 tas->envv[i] = NULL;
[169]652#if 0
[1]653 tas->trusted_users[i] = (uid_t) -1;
[169]654#endif
[1]655 }
656
657 tas->run_user_uid = (uid_t) getuid();
658 tas->run_user_gid = (gid_t) getgid();
659
660 tas->com_fd = -1;
661 tas->com_ti = -1;
662 return;
663}
664
665
[22]666int sh_ext_tas_add_envv(sh_tas_t * tas, const char * key, const char * val)
[1]667{
668 size_t sk = 0, sv = 0;
669 int si;
670
671 SL_ENTER(_("sh_ext_tas_add_envv"));
672
673 if (tas == NULL || (key == NULL && val == NULL) ||
674 tas->envc >= 30)
675 {
676 SL_RETURN (-1, _("sh_ext_tas_add_envv"));
677 }
678 if (key != NULL)
679 sk = strlen(key) + 1;
680 if (val != NULL)
681 sv = strlen(val) + 1;
682
[34]683 if (!sl_ok_adds(sk, sv))
684 {
685 SL_RETURN (-1, _("sh_ext_tas_add_envv"));
686 }
[1]687 si = tas->envc;
688 tas->envv[si] = SH_ALLOC(sk + sv);
689
690 if (key != NULL)
691 {
692 (void) sl_strlcpy(tas->envv[si], key, sk+sv);
693 (void) sl_strlcat(tas->envv[si], "=", sk+sv);
694 if (val != NULL)
695 (void) sl_strlcat(tas->envv[si], val, sk+sv);
696 }
697 else
698 (void) sl_strlcpy(tas->envv[si], val, sv);
699
700 ++(tas->envc);
701 SL_RETURN ((tas->envc), _("sh_ext_tas_add_envv"));
702}
703
704int sh_ext_tas_rm_argv(sh_tas_t * tas)
705{
706 int last;
707
708 SL_ENTER(_("sh_ext_tas_rm_argv"));
709 if (tas == NULL || tas->argc == 0)
710 {
711 SL_RETURN (-1, _("sh_ext_tas_rm_argv"));
712 }
713
714 last = (tas->argc - 1);
715 --(tas->argc);
716 SH_FREE(tas->argv[last]);
717 tas->argv[last] = NULL;
718 SL_RETURN ((tas->argc), _("sh_ext_tas_rm_argv"));
719}
720
[22]721int sh_ext_tas_add_argv(sh_tas_t * tas, const char * val)
[1]722{
723 size_t sv = 0;
724 int si;
725
726 SL_ENTER(_("sh_ext_tas_add_argv"));
727
728 if (tas == NULL || val == NULL ||
729 tas->argc >= 30)
730 {
731 SL_RETURN (-1, _("sh_ext_tas_add_argv"));
732 }
733
734 if (val != NULL)
735 sv = strlen(val) + 1;
736
737 si = tas->argc;
738 tas->argv[si] = SH_ALLOC(sv);
739
740 (void) sl_strlcpy(tas->argv[si], val, sv);
741
742 ++(tas->argc);
743 SL_RETURN ((tas->argc), _("sh_ext_tas_add_argv"));
744}
745
[22]746void sh_ext_tas_command(sh_tas_t * tas, const char * command)
[1]747{
748 size_t len = sl_strlen(command);
749 tas->command = SH_ALLOC(len+1);
750 (void) sl_strlcpy(tas->command, command, len+1);
751 return;
752}
753
754void sh_ext_tas_free(sh_tas_t * tas)
755{
756 int i;
757 if (NULL != tas->command) SH_FREE(tas->command);
758
759 for (i = 0; i < 32; ++i)
760 {
761 if (NULL != tas->argv[i]) SH_FREE(tas->argv[i]);
762 if (NULL != tas->envv[i]) SH_FREE(tas->envv[i]);
763 }
764
765 if (tas->com_ti != (-1))
766 {
767 (void) sl_close(tas->com_ti);
768 tas->com_ti = -1;
769 tas->com_fd = -1;
770 }
771
772 return;
773}
774
[211]775/* Execute command, return first line of output
776 * ifconfig | grep -1 lo | tail -n 1 | sed s/.*inet addr:\([0-9.]*\)\(.*\)/\1/
777 */
778char * sh_ext_popen_str (char * command)
779{
780 sh_tas_t task;
781 struct sigaction new_act;
782 struct sigaction old_act;
783 char dir[SH_PATHBUF];
784 char * p;
785 char * out = NULL;
786 int status;
[1]787
[211]788 SL_ENTER(_("sh_ext_popen_str"));
789
790 sh_ext_tas_init(&task);
791
792 (void) sh_ext_tas_add_envv (&task, _("SHELL"),
793 _("/bin/sh"));
794 (void) sh_ext_tas_add_envv (&task, _("PATH"),
795 _("/sbin:/bin:/usr/sbin:/usr/bin:/usr/ucb"));
796 (void) sh_ext_tas_add_envv (&task, _("IFS"), " \n\t");
797 if (sh.timezone != NULL)
798 {
799 (void) sh_ext_tas_add_envv(&task, "TZ", sh.timezone);
800 }
801
802 sh_ext_tas_command(&task, _("/bin/sh"));
803
804 (void) sh_ext_tas_add_argv(&task, _("/bin/sh"));
805 (void) sh_ext_tas_add_argv(&task, _("-c"));
806 (void) sh_ext_tas_add_argv(&task, command);
807
808 task.rw = 'r';
809 task.fork_twice = S_FALSE;
810
811 status = sh_ext_popen(&task);
812
813 if (status != 0)
814 {
815 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN,
816 _("Could not open pipe"), _("sh_ext_popen_str"));
817 SL_RETURN ((NULL), _("sh_ext_popen_str"));
818 }
819
820 /* ignore SIGPIPE (instead get EPIPE if connection is closed)
821 */
822 new_act.sa_handler = SIG_IGN;
823 (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &new_act, &old_act);
824
825 /* read from the open pipe
826 */
827 if (task.pipe != NULL)
828 {
829 int try = 1200; /* 1000 * 0.1 = 120 sec */
830 sh_string * s = sh_string_new(0);
831 do {
832 sh_string_read(s, task.pipe, 0);
833 if (sh_string_len(s) == 0)
834 {
835 --try; retry_msleep(0, 100);
836 }
837 } while (sh_string_len(s) == 0 && try != 0);
838
839 if (sh_string_len(s) == 0)
840 {
841 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN,
842 _("No output from command"), _("sh_ext_popen_str"));
843 }
844
845 out = sh_util_strdup(sh_string_str(s));
846 sh_string_destroy(&s);
847 }
848
849 /* restore old signal handler
850 */
851 (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &old_act, NULL);
852
853 /* close pipe and return exit status
854 */
855 (void) sh_ext_pclose(&task);
856 sh_ext_tas_free (&task);
857 SL_RETURN ((out), _("sh_ext_popen_str"));
858}
859
860
861
862
[1]863/* --------------- EXTERN STUFF ------------------- */
864
865#if defined(WITH_EXTERNAL)
866
867typedef struct _sh_com_t
868{
869 char type[4];
870
871 int for_c;
872 char * for_v[32];
873 int fand_c;
874 char * fand_v[32];
875 int fnot_c;
876 char * fnot_v[32];
877 time_t deadtime;
878 time_t last_run;
879
880 sh_tas_t tas;
881
882 struct _sh_com_t * next;
883
884} sh_com_t;
885
886
887static
888void set3 (char * pos, char c1, char c2, char c3)
889{
890 pos[0] = c1;
891 pos[1] = c2;
892 pos[2] = c3;
893 pos[3] = '\0';
894 return;
895}
896
897
898
899/* initialize the external command structure
900 */
901static
902sh_com_t * command_init(void)
903{
904 int i;
905 uid_t ff_euid;
906 sh_com_t * ext_com = NULL;
907
908 SL_ENTER(_("command_init"));
909
910 ext_com = (sh_com_t *) SH_ALLOC(sizeof(sh_com_t));
911
912 if (!ext_com)
913 {
[170]914 SL_RETURN( NULL, _("command_init"));
[1]915 }
916
917 sh_ext_tas_init (&(ext_com->tas));
918
919 (void) sl_get_euid(&ff_euid);
[169]920#if 0
[1]921 ext_com->tas.trusted_users[0] = (uid_t) 0;
922 ext_com->tas.trusted_users[1] = (uid_t) (ff_euid);
[169]923#endif
[1]924
925 /* ------------------------------------------------- */
926
927 set3(ext_com->type, 'l', 'o', 'g');
928 ext_com->for_c = 0;
929 ext_com->fand_c = 0;
930 ext_com->fnot_c = 0;
931 ext_com->deadtime = 0;
932 ext_com->last_run = 0;
933
934 for (i = 0; i < 32; ++i)
935 {
936 ext_com->for_v[i] = NULL;
937 ext_com->fand_v[i] = NULL;
938 ext_com->fnot_v[i] = NULL;
939 }
940 ext_com->next = NULL;
941
[170]942 SL_RETURN( ext_com, _("command_init"));
[1]943}
944
945/* the list of external commands
946 */
947static sh_com_t * ext_coms = NULL;
948
949/* if -1, allocation of last command has failed,
950 * thus don't fill in options
951 */
952static int ext_failed = -1;
953
954static
[22]955int sh_ext_add_envv(const char * key, const char * val)
[1]956{
[34]957 int retval;
958
[1]959 SL_ENTER(_("sh_ext_add_envv"));
960
961 if (ext_coms == NULL || ext_failed == (-1) ||
962 (key == NULL && val == NULL) ||
963 ext_coms->tas.envc >= 30)
964 {
965 SL_RETURN (-1, _("sh_ext_add_envv"));
966 }
967
[34]968 retval = sh_ext_tas_add_envv(&(ext_coms->tas), key, val);
[1]969
[34]970 if (retval >= 0)
971 retval = 0;
972
973 SL_RETURN (retval, _("sh_ext_add_envv"));
[1]974}
975
976
977
978static
[22]979int sh_ext_init(const char * command)
[1]980{
981 sh_com_t * retval;
982 size_t size;
983
984 SL_ENTER(_("sh_ext_init"));
985
986 if (command == NULL)
987 {
988 SL_RETURN (-1, _("sh_ext_init"));
989 }
990 size = strlen(command);
991 if (command[0] != '/' || size < 2)
992 {
993 SL_RETURN (-1, _("sh_ext_init"));
994 }
995
996 if (NULL == (retval = command_init()))
997 {
998 SL_RETURN (-1, _("sh_ext_init"));
999 }
1000
1001 sh_ext_tas_command(&(retval->tas), command);
1002
1003 if (sh.timezone != NULL)
1004 {
1005 (void) sh_ext_add_envv( "TZ", sh.timezone);
1006 }
1007
1008 retval->next = ext_coms;
1009 ext_coms = retval;
1010 SL_RETURN (0, _("sh_ext_init"));
1011}
1012
1013static
[22]1014int sh_ext_uid (const char * user, /*@out@*/uid_t * uid, /*@out@*/gid_t * gid)
[1]1015{
[131]1016 struct passwd * tempres;
1017#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1018 struct passwd pwd;
1019 char buffer[SH_PWBUF_SIZE];
1020#endif
[1]1021
1022 SL_ENTER(_("sh_ext_uid"));
1023
1024 *uid = (uid_t)-1; *gid = (gid_t)-1;
1025
1026 if (user == NULL)
1027 {
1028 SL_RETURN (-1, _("sh_ext_uid"));
1029 }
[131]1030
1031#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1032 sh_getpwnam_r(user, &pwd, buffer, sizeof(buffer), &tempres);
1033#else
[1]1034 tempres = sh_getpwnam(user);
[131]1035#endif
[1]1036
1037 if (NULL != tempres)
1038 {
1039 *uid = tempres->pw_uid;
1040 *gid = tempres->pw_gid;
1041 SL_RETURN (0, _("sh_ext_uid"));
1042 }
1043
1044 SL_RETURN (-1, _("sh_ext_uid"));
1045}
1046
1047
1048static
[22]1049int sh_ext_add (const char * argstring, int * ntok, char * stok[])
[1]1050{
1051 int i = 0;
1052 size_t s;
1053 char * p;
[22]1054 char * new;
1055 size_t len;
[1]1056
1057 SL_ENTER(_("sh_ext_add"));
1058
1059 if (NULL == argstring)
1060 {
1061 SL_RETURN((-1), _("sh_ext_add"));
1062 }
1063
[22]1064 len = strlen(argstring) + 1;
1065 new = SH_ALLOC(len);
1066 sl_strlcpy(new, argstring, len);
1067
[1]1068 do
1069 {
[131]1070#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1071 char * saveptr;
[1]1072 if (i == 0)
[131]1073 p = strtok_r (new, ", \t", &saveptr);
1074 else
1075 p = strtok_r (NULL, ", \t", &saveptr);
1076#else
1077 if (i == 0)
[22]1078 p = strtok (new, ", \t");
[1]1079 else
1080 p = strtok (NULL, ", \t");
[131]1081#endif
1082
[1]1083 if (p == NULL)
1084 break;
1085
1086 s = strlen(p) + 1;
1087 if (stok[i] != NULL)
1088 SH_FREE(stok[i]);
1089 stok[i] = SH_ALLOC(s);
1090 (void) sl_strlcpy(stok[i], p, s);
1091
1092 ++i;
1093 if (i == 30)
1094 break;
1095 }
1096 while (p != NULL);
1097
1098 *ntok = i;
[22]1099 SH_FREE(new);
[1]1100
1101 SL_RETURN (0, _("sh_ext_add"));
1102}
1103
1104/*********************************************************
1105 *
1106 * Public functions
1107 *
1108 *
1109 *********************************************************/
1110
1111/*
1112 * -- start a new external command, and add it to the list
1113 */
[22]1114int sh_ext_setcommand(const char * cmd)
[1]1115{
1116 int i;
1117
1118 SL_ENTER(_("sh_ext_setcommand"));
1119 if ( (i = sh_ext_init(cmd)) < 0)
1120 ext_failed = -1;
1121 else
1122 ext_failed = 0;
1123 SL_RETURN( i, _("sh_ext_setcommand"));
1124}
1125
1126
1127/*
1128 * -- clean up the command list
1129 */
1130int sh_ext_cleanup(void)
1131{
1132 int i;
1133 sh_com_t * retval;
1134
1135 SL_ENTER(_("sh_ext_cleanup"));
1136
1137 while (ext_coms != NULL)
1138 {
1139 retval = ext_coms;
1140 ext_coms = retval->next;
1141
1142 sh_ext_tas_free (&(retval->tas));
1143
1144 for (i = 0; i < 32; ++i)
1145 {
1146 if (NULL != retval->for_v[i]) SH_FREE(retval->for_v[i]);
1147 if (NULL != retval->fand_v[i]) SH_FREE(retval->fand_v[i]);
1148 if (NULL != retval->fnot_v[i]) SH_FREE(retval->fnot_v[i]);
1149 }
1150
1151 SH_FREE(retval);
1152
1153 }
1154
1155 SL_RETURN (0, _("sh_ext_cleanup"));
1156}
1157
1158/*
[164]1159 * -- explicitely close a command
1160 */
1161int sh_ext_close_command (const char * str)
1162{
1163 (void) str;
1164 if (ext_coms == NULL || ext_failed == (-1))
1165 return (-1);
1166 ext_failed = (-1);
1167 return 0;
1168}
1169
1170/*
[1]1171 * -- add keywords to the OR filter
1172 */
[22]1173int sh_ext_add_or (const char * str)
[1]1174{
1175 if (ext_coms == NULL || ext_failed == (-1))
1176 return (-1);
1177 return (sh_ext_add (str, &(ext_coms->for_c), ext_coms->for_v));
1178}
1179
1180/*
1181 * -- add keywords to the AND filter
1182 */
[22]1183int sh_ext_add_and (const char * str)
[1]1184{
1185 if (ext_coms == NULL || ext_failed == (-1))
1186 return (-1);
1187 return (sh_ext_add (str, &(ext_coms->fand_c), ext_coms->fand_v));
1188}
1189
1190/*
1191 * -- add keywords to the NOT filter
1192 */
[22]1193int sh_ext_add_not (const char * str)
[1]1194{
1195 if (ext_coms == NULL || ext_failed == (-1))
1196 return (-1);
1197 return (sh_ext_add (str, &(ext_coms->fnot_c), ext_coms->fnot_v));
1198}
1199
1200/*
1201 * -- add keywords to the CL argument list
1202 */
[22]1203int sh_ext_add_argv (const char * str)
[1]1204{
1205 if (ext_coms == NULL || ext_failed == (-1))
1206 return (-1);
1207 return (sh_ext_add (str, &(ext_coms->tas.argc), ext_coms->tas.argv));
1208}
1209
1210/*
1211 * -- add a path to the environment
1212 */
[22]1213int sh_ext_add_default (const char * dummy)
[1]1214{
[22]1215 char * p = NULL;
[1]1216 int i;
[132]1217 char dir[SH_PATHBUF];
[1]1218
1219 SL_ENTER(_("sh_ext_add_default"));
1220 if (dummy[0] == 'n' || dummy[0] == 'N' ||
1221 dummy[0] == 'f' || dummy[0] == 'F' || dummy[0] == '0')
1222 {
1223 SL_RETURN(0, _("sh_ext_add_default"));
1224 }
[132]1225 p = sh_unix_getUIDdir (SH_ERR_ERR, (uid_t) ext_coms->tas.run_user_uid,
1226 dir, sizeof(dir));
[1]1227 if (p)
1228 (void) sh_ext_add_envv (_("HOME"), p);
1229 (void) sh_ext_add_envv (_("SHELL"), _("/bin/sh"));
[211]1230 (void) sh_ext_add_envv (_("PATH"), _("/sbin:/bin:/usr/sbin:/usr/bin"));
1231 (void) sh_ext_add_envv (_("IFS"), " \n\t");
[1]1232 i = (p == NULL ? (-1) : 0);
1233 SL_RETURN(i, _("sh_ext_add_default"));
1234}
1235
1236/*
1237 * -- add an environment variable
1238 */
[22]1239int sh_ext_add_environ (const char * str)
[1]1240{
1241 int i;
[49]1242
[1]1243 SL_ENTER(_("sh_ext_add_environ"));
1244 i = sh_ext_add_envv (NULL, str);
1245 SL_RETURN(i, _("sh_ext_add_environ"));
1246}
1247
1248/*
1249 * -- set deadtime
1250 */
[22]1251int sh_ext_deadtime (const char * str)
[1]1252{
1253 long deadtime = 0;
1254 char * tail = NULL;
1255
1256 SL_ENTER(_("sh_ext_deadtime"));
1257
1258 if (ext_coms == NULL || ext_failed == (-1) || str == NULL)
1259 {
[170]1260 SL_RETURN (-1, _("sh_ext_deadtime"));
[1]1261 }
1262 deadtime = strtol(str, &tail, 10);
1263 if (tail == str || deadtime < 0 || deadtime == LONG_MAX)
1264 {
[170]1265 SL_RETURN (-1, _("sh_ext_deadtime"));
[1]1266 }
1267
1268 ext_coms->deadtime = (time_t) deadtime;
[170]1269 SL_RETURN (0, _("sh_ext_deadtime"));
[1]1270}
1271
1272/*
1273 * -- define type
1274 */
[22]1275int sh_ext_type (const char * str)
[1]1276{
1277 SL_ENTER(_("sh_ext_type"));
1278
1279 if (ext_coms == NULL || ext_failed == (-1) || str == NULL)
1280 {
1281 SL_RETURN((-1), _("sh_ext_type"));
1282 }
1283
1284 if (strlen(str) != 3)
1285 {
1286 SL_RETURN((-1), _("sh_ext_type"));
1287 }
1288
1289 set3(ext_coms->type, str[0], str[1], str[2]);
1290
1291 if (str[0] == 'l' && str[1] == 'o' && str[2] == 'g')
1292 ext_coms->tas.rw = 'w';
1293 else if (str[0] == 's' && str[1] == 'r' && str[2] == 'v')
1294 ext_coms->tas.rw = 'w';
1295 else if (str[0] == 'm' && str[1] == 'o' && str[2] == 'n')
1296 ext_coms->tas.rw = 'r';
1297 else
1298 {
1299 SL_RETURN((-1), _("sh_ext_type"));
1300 }
1301
1302 SL_RETURN(0, _("sh_ext_type"));
1303}
1304
1305
1306
1307/*
1308 * -- define checksum
1309 */
[22]1310int sh_ext_checksum (const char * str)
[1]1311{
1312 SL_ENTER(_("sh_ext_checksum"));
1313 if (ext_coms == NULL || ext_failed == (-1) || str == NULL)
1314 {
1315 SL_RETURN((-1), _("sh_ext_checksum"));
1316 }
1317
1318 if (sl_strlen(str) != KEY_LEN)
1319 {
1320 SL_RETURN((-1), _("sh_ext_checksum"));
1321 }
1322
1323 (void) sl_strlcpy (ext_coms->tas.checksum, str, KEY_LEN+1);
1324
1325 SL_RETURN((0), _("sh_ext_checksum"));
1326}
1327
1328/*
1329 * -- choose privileges
1330 */
[22]1331int sh_ext_priv (const char * c)
[1]1332{
1333
1334 uid_t me_uid;
1335 gid_t me_gid;
1336
1337 SL_ENTER(_("sh_ext_priv"));
1338 if (0 == sh_ext_uid (c, &me_uid, &me_gid))
1339 {
1340 ext_coms->tas.run_user_uid = me_uid;
1341 ext_coms->tas.run_user_gid = me_gid;
1342 if (me_uid != (uid_t) 0)
1343 ext_coms->tas.privileged = 0;
1344 SL_RETURN((0), _("sh_ext_priv"));
1345 }
1346
1347 SL_RETURN (-1, _("sh_ext_priv"));
1348}
1349
1350
1351
1352
1353/*
1354 * -- check filters
1355 */
1356static int sh_ext_filter (char * message, sh_com_t * task)
1357{
1358 int i;
1359 int j = 0;
1360 time_t now_time;
1361
1362 SL_ENTER(_("sh_ext_filter"));
1363
1364 /* Presence of any of these keywords prevents execution.
1365 */
1366 if (task->fnot_c > 0)
1367 {
1368 for (i = 0; i < task->fnot_c; ++i)
1369 {
1370 if (NULL != sl_strstr(message, task->fnot_v[i]))
1371 {
1372 SL_RETURN ((-1), _("sh_ext_filter"));
1373 }
1374 }
1375 }
1376
1377 /* Presence of all of these keywords is required for execution.
1378 */
1379 if (task->fand_c > 0)
1380 {
1381 j = 0;
1382
1383 for (i = 0; i < task->fand_c; ++i)
1384 if (NULL != sl_strstr(message, task->fand_v[i]))
1385 ++j;
1386
1387 if (j != task->fand_c)
1388 {
1389 SL_RETURN ((-1), _("sh_ext_filter"));
1390 }
1391
1392 }
1393
1394 /* Presence of at least one of these keywords is required for execution.
1395 */
1396 if (task->for_c > 0)
1397 {
1398 for (i = 0; i < task->for_c; ++i)
1399 {
1400 if (NULL != sl_strstr(message, task->for_v[i]))
1401 {
1402 goto checkdeadtime;
1403 }
1404 }
1405 SL_RETURN ((-1), _("sh_ext_filter"));
1406 }
1407
1408 checkdeadtime:
1409 if (task->deadtime != (time_t) 0) /* deadtime */
1410 {
1411 now_time = time (NULL);
1412
1413 if (task->last_run == (time_t) 0)
1414 {
1415 task->last_run = now_time;
1416 }
1417 else if ((time_t)(now_time-task->last_run) < task->deadtime)
1418 {
1419 SL_RETURN ((-1), _("sh_ext_filter"));
1420 }
1421 else
1422 {
1423 task->last_run = now_time;
1424 }
1425 }
1426
1427 SL_RETURN ((0), _("sh_ext_filter"));
1428}
1429
1430
1431
1432/*
1433 * -- execute external script/program
1434 */
1435int sh_ext_execute (char t1, char t2, char t3, /*@null@*/char * message,
1436 size_t msg_siz)
1437{
1438 int caperr;
1439 sh_com_t * listval = ext_coms;
1440 int status = 0;
1441 char * tmp;
[132]1442 char errbuf[SH_ERRBUF_SIZE];
[1]1443
1444 static int some_error = 0;
1445
1446 struct sigaction new_act;
1447 struct sigaction old_act;
1448
1449 SL_ENTER(_("sh_ext_execute"));
1450
1451 PDBG_OPEN;
1452
1453 if (listval == NULL || message == NULL)
1454 {
1455 SL_RETURN ((-1), _("sh_ext_execute"));
1456 }
1457
1458 PDBG(-1);
1459
1460 if (msg_siz == 0)
1461 msg_siz = sl_strlen(message);
1462
1463
1464 /* ignore SIGPIPE (instead get EPIPE if connection is closed)
1465 */
1466 new_act.sa_handler = SIG_IGN;
1467 (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &new_act, &old_act);
1468
1469 while (listval != NULL)
1470 {
1471 PDBG(-2);
1472 if (t1 == listval->type[0] &&
1473 t2 == listval->type[1] &&
1474 t3 == listval->type[2] &&
1475 0 == sh_ext_filter (message, listval))
1476 {
1477 PDBG(-3);
1478
1479 if (0 != (caperr = sl_get_cap_sub()))
1480 {
1481 sh_error_handle((-1), FIL__, __LINE__, caperr, MSG_E_SUBGEN,
[132]1482 sh_error_message (caperr, errbuf, sizeof(errbuf)),
[1]1483 _("sl_get_cap_sub"));
1484 }
1485 if (0 == sh_ext_popen (&(listval->tas)))
1486 {
1487 PDBG_OPEN;
1488 PDBG(-4);
1489 if (NULL != listval->tas.pipe && listval->tas.rw == 'w')
1490 {
1491 PDBG(-5);
1492 if (message != NULL)
1493 {
1494 PDBG(-6);
1495 status = (int) write (listval->tas.pipeFD,
1496 message, msg_siz);
1497 if (status >= 0)
1498 status = (int) write (listval->tas.pipeFD, "\n", 1);
1499 }
1500 PDBG_D(status);
1501 if (status >= 0)
1502 status = (int) write (listval->tas.pipeFD, "[", 1);
1503 PDBG_D(status);
1504 if (status >= 0)
1505 status = (int) write (listval->tas.pipeFD, "E", 1);
1506 PDBG_D(status);
1507 if (status >= 0)
1508 status = (int) write (listval->tas.pipeFD, "O", 1);
1509 PDBG_D(status);
1510 if (status >= 0)
1511 status = (int) write (listval->tas.pipeFD, "F", 1);
1512 PDBG_D(status);
1513 if (status >= 0)
1514 status = (int) write (listval->tas.pipeFD, "]", 1);
1515 PDBG_D(status);
1516 if (status >= 0)
1517 status = (int) write (listval->tas.pipeFD, "\n", 1);
1518 PDBG_D(status);
1519 if (status >= 0)
1520 {
1521 some_error = 0;
1522 }
1523 if ((status < 0) && (some_error == 0))
1524 {
1525 some_error = 1;
1526 PDBG_S("some error");
1527 PDBG_D(status);
1528 tmp = sh_util_safe_name (listval->tas.command);
1529
1530 if (tmp)
1531 {
1532 if (listval->tas.privileged == 0 &&
1533 (0 == getuid() || 0 != sl_is_suid()) )
1534 sh_error_handle((-1), FIL__, __LINE__, 0,
1535 MSG_NOEXEC,
1536 (UID_CAST) listval->tas.run_user_uid,
1537 tmp);
1538 else
1539 sh_error_handle((-1), FIL__, __LINE__, 0,
1540 MSG_NOEXEC,
1541 (UID_CAST) getuid(), tmp);
1542
1543 SH_FREE(tmp);
1544 }
1545
1546 }
1547 PDBG(-7);
1548 (void) fflush(listval->tas.pipe);
1549 }
1550 PDBG(-8);
1551 (void) sh_ext_pclose(&(listval->tas));
1552 }
1553 else
1554 {
1555 PDBG_OPEN;
1556 PDBG_S("0 != sh_ext_popen()");
1557 }
1558 if (0 != (caperr = sl_drop_cap_sub()))
1559 {
1560 sh_error_handle((-1), FIL__, __LINE__, caperr, MSG_E_SUBGEN,
[132]1561 sh_error_message (caperr, errbuf, sizeof(errbuf)),
[1]1562 _("sl_drop_cap_sub"));
1563 }
1564
1565 }
1566 listval = listval->next;
1567 }
1568 PDBG_OPEN;
1569 PDBG_S("no more commands");
1570
1571 /* restore old signal handler
1572 */
1573 (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &old_act, NULL);
1574 PDBG_S("return");
1575 PDBG_CLOSE;
1576
1577 SL_RETURN ((0), _("sh_ext_execute"));
1578}
1579
1580
1581/* #if defined(WITH_EXTERNAL) */
1582#endif
Note: See TracBrowser for help on using the repository browser.