source: trunk/src/sh_extern.c@ 288

Last change on this file since 288 was 275, checked in by katerina, 15 years ago

Fix for ticket #195 (broken immediate mailing of highest priority messages).

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