source: trunk/src/sh_extern.c@ 271

Last change on this file since 271 was 252, checked in by katerina, 15 years ago

Add code to check for stale file records on close() and fclose(), fix sl_close() to handle open stream (ticket #163).

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 */
[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
[211]811/* Execute command, return first line of output
812 * ifconfig | grep -1 lo | tail -n 1 | sed s/.*inet addr:\([0-9.]*\)\(.*\)/\1/
813 */
814char * sh_ext_popen_str (char * command)
815{
816 sh_tas_t task;
817 struct sigaction new_act;
818 struct sigaction old_act;
819 char * out = NULL;
820 int status;
[1]821
[211]822 SL_ENTER(_("sh_ext_popen_str"));
823
824 sh_ext_tas_init(&task);
825
826 (void) sh_ext_tas_add_envv (&task, _("SHELL"),
827 _("/bin/sh"));
828 (void) sh_ext_tas_add_envv (&task, _("PATH"),
829 _("/sbin:/bin:/usr/sbin:/usr/bin:/usr/ucb"));
830 (void) sh_ext_tas_add_envv (&task, _("IFS"), " \n\t");
831 if (sh.timezone != NULL)
832 {
833 (void) sh_ext_tas_add_envv(&task, "TZ", sh.timezone);
834 }
835
836 sh_ext_tas_command(&task, _("/bin/sh"));
837
838 (void) sh_ext_tas_add_argv(&task, _("/bin/sh"));
839 (void) sh_ext_tas_add_argv(&task, _("-c"));
840 (void) sh_ext_tas_add_argv(&task, command);
841
842 task.rw = 'r';
843 task.fork_twice = S_FALSE;
844
845 status = sh_ext_popen(&task);
846
847 if (status != 0)
848 {
849 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN,
850 _("Could not open pipe"), _("sh_ext_popen_str"));
851 SL_RETURN ((NULL), _("sh_ext_popen_str"));
852 }
853
854 /* ignore SIGPIPE (instead get EPIPE if connection is closed)
855 */
856 new_act.sa_handler = SIG_IGN;
857 (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &new_act, &old_act);
858
859 /* read from the open pipe
860 */
861 if (task.pipe != NULL)
862 {
863 int try = 1200; /* 1000 * 0.1 = 120 sec */
864 sh_string * s = sh_string_new(0);
865 do {
866 sh_string_read(s, task.pipe, 0);
867 if (sh_string_len(s) == 0)
868 {
869 --try; retry_msleep(0, 100);
870 }
871 } while (sh_string_len(s) == 0 && try != 0);
872
873 if (sh_string_len(s) == 0)
874 {
875 sh_error_handle(SH_ERR_ALL, FIL__, __LINE__, status, MSG_E_SUBGEN,
876 _("No output from command"), _("sh_ext_popen_str"));
877 }
878
879 out = sh_util_strdup(sh_string_str(s));
880 sh_string_destroy(&s);
881 }
882
883 /* restore old signal handler
884 */
885 (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &old_act, NULL);
886
887 /* close pipe and return exit status
888 */
889 (void) sh_ext_pclose(&task);
890 sh_ext_tas_free (&task);
891 SL_RETURN ((out), _("sh_ext_popen_str"));
892}
893
894
895
896
[1]897/* --------------- EXTERN STUFF ------------------- */
898
899#if defined(WITH_EXTERNAL)
900
901typedef struct _sh_com_t
902{
903 char type[4];
904
[215]905 sh_filter_type * filter;
906
[1]907 time_t deadtime;
908 time_t last_run;
909
910 sh_tas_t tas;
911
912 struct _sh_com_t * next;
913
914} sh_com_t;
915
916
917static
918void set3 (char * pos, char c1, char c2, char c3)
919{
920 pos[0] = c1;
921 pos[1] = c2;
922 pos[2] = c3;
923 pos[3] = '\0';
924 return;
925}
926
927
928
929/* initialize the external command structure
930 */
931static
932sh_com_t * command_init(void)
933{
934 uid_t ff_euid;
935 sh_com_t * ext_com = NULL;
936
937 SL_ENTER(_("command_init"));
938
939 ext_com = (sh_com_t *) SH_ALLOC(sizeof(sh_com_t));
940
941 if (!ext_com)
942 {
[170]943 SL_RETURN( NULL, _("command_init"));
[1]944 }
945
946 sh_ext_tas_init (&(ext_com->tas));
947
948 (void) sl_get_euid(&ff_euid);
[169]949#if 0
[1]950 ext_com->tas.trusted_users[0] = (uid_t) 0;
951 ext_com->tas.trusted_users[1] = (uid_t) (ff_euid);
[169]952#endif
[1]953
954 /* ------------------------------------------------- */
955
956 set3(ext_com->type, 'l', 'o', 'g');
[215]957 ext_com->filter = NULL;
[1]958 ext_com->deadtime = 0;
959 ext_com->last_run = 0;
960
961 ext_com->next = NULL;
962
[170]963 SL_RETURN( ext_com, _("command_init"));
[1]964}
965
966/* the list of external commands
967 */
968static sh_com_t * ext_coms = NULL;
969
970/* if -1, allocation of last command has failed,
971 * thus don't fill in options
972 */
973static int ext_failed = -1;
974
975static
[22]976int sh_ext_add_envv(const char * key, const char * val)
[1]977{
[34]978 int retval;
979
[1]980 SL_ENTER(_("sh_ext_add_envv"));
981
982 if (ext_coms == NULL || ext_failed == (-1) ||
983 (key == NULL && val == NULL) ||
984 ext_coms->tas.envc >= 30)
985 {
986 SL_RETURN (-1, _("sh_ext_add_envv"));
987 }
988
[34]989 retval = sh_ext_tas_add_envv(&(ext_coms->tas), key, val);
[1]990
[34]991 if (retval >= 0)
992 retval = 0;
993
994 SL_RETURN (retval, _("sh_ext_add_envv"));
[1]995}
996
997
998
999static
[22]1000int sh_ext_init(const char * command)
[1]1001{
1002 sh_com_t * retval;
1003 size_t size;
1004
1005 SL_ENTER(_("sh_ext_init"));
1006
1007 if (command == NULL)
1008 {
1009 SL_RETURN (-1, _("sh_ext_init"));
1010 }
1011 size = strlen(command);
1012 if (command[0] != '/' || size < 2)
1013 {
1014 SL_RETURN (-1, _("sh_ext_init"));
1015 }
1016
1017 if (NULL == (retval = command_init()))
1018 {
1019 SL_RETURN (-1, _("sh_ext_init"));
1020 }
1021
1022 sh_ext_tas_command(&(retval->tas), command);
1023
1024 if (sh.timezone != NULL)
1025 {
1026 (void) sh_ext_add_envv( "TZ", sh.timezone);
1027 }
1028
1029 retval->next = ext_coms;
1030 ext_coms = retval;
1031 SL_RETURN (0, _("sh_ext_init"));
1032}
1033
1034static
[22]1035int sh_ext_uid (const char * user, /*@out@*/uid_t * uid, /*@out@*/gid_t * gid)
[1]1036{
[131]1037 struct passwd * tempres;
1038#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1039 struct passwd pwd;
[227]1040 char * buffer = SH_ALLOC(SH_PWBUF_SIZE);
[131]1041#endif
[1]1042
1043 SL_ENTER(_("sh_ext_uid"));
1044
1045 *uid = (uid_t)-1; *gid = (gid_t)-1;
1046
1047 if (user == NULL)
1048 {
[227]1049#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1050 SH_FREE(buffer);
1051#endif
[1]1052 SL_RETURN (-1, _("sh_ext_uid"));
1053 }
[131]1054
1055#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
[227]1056 sh_getpwnam_r(user, &pwd, buffer, SH_PWBUF_SIZE, &tempres);
[131]1057#else
[1]1058 tempres = sh_getpwnam(user);
[131]1059#endif
[1]1060
1061 if (NULL != tempres)
1062 {
1063 *uid = tempres->pw_uid;
1064 *gid = tempres->pw_gid;
[227]1065#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1066 SH_FREE(buffer);
1067#endif
[1]1068 SL_RETURN (0, _("sh_ext_uid"));
1069 }
1070
[227]1071#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R)
1072 SH_FREE(buffer);
1073#endif
[1]1074 SL_RETURN (-1, _("sh_ext_uid"));
1075}
1076
1077
1078static
[22]1079int sh_ext_add (const char * argstring, int * ntok, char * stok[])
[1]1080{
1081 int i = 0;
1082 size_t s;
1083 char * p;
[22]1084 char * new;
1085 size_t len;
[1]1086
1087 SL_ENTER(_("sh_ext_add"));
1088
1089 if (NULL == argstring)
1090 {
1091 SL_RETURN((-1), _("sh_ext_add"));
1092 }
1093
[22]1094 len = strlen(argstring) + 1;
1095 new = SH_ALLOC(len);
1096 sl_strlcpy(new, argstring, len);
1097
[1]1098 do
1099 {
[131]1100#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1101 char * saveptr;
[1]1102 if (i == 0)
[131]1103 p = strtok_r (new, ", \t", &saveptr);
1104 else
1105 p = strtok_r (NULL, ", \t", &saveptr);
1106#else
1107 if (i == 0)
[22]1108 p = strtok (new, ", \t");
[1]1109 else
1110 p = strtok (NULL, ", \t");
[131]1111#endif
1112
[1]1113 if (p == NULL)
1114 break;
1115
1116 s = strlen(p) + 1;
1117 if (stok[i] != NULL)
1118 SH_FREE(stok[i]);
1119 stok[i] = SH_ALLOC(s);
1120 (void) sl_strlcpy(stok[i], p, s);
1121
1122 ++i;
1123 if (i == 30)
1124 break;
1125 }
1126 while (p != NULL);
1127
1128 *ntok = i;
[22]1129 SH_FREE(new);
[1]1130
1131 SL_RETURN (0, _("sh_ext_add"));
1132}
1133
1134/*********************************************************
1135 *
1136 * Public functions
1137 *
1138 *
1139 *********************************************************/
1140
1141/*
1142 * -- start a new external command, and add it to the list
1143 */
[22]1144int sh_ext_setcommand(const char * cmd)
[1]1145{
1146 int i;
1147
1148 SL_ENTER(_("sh_ext_setcommand"));
1149 if ( (i = sh_ext_init(cmd)) < 0)
1150 ext_failed = -1;
1151 else
1152 ext_failed = 0;
1153 SL_RETURN( i, _("sh_ext_setcommand"));
1154}
1155
1156
1157/*
1158 * -- clean up the command list
1159 */
1160int sh_ext_cleanup(void)
1161{
1162 sh_com_t * retval;
1163
1164 SL_ENTER(_("sh_ext_cleanup"));
1165
1166 while (ext_coms != NULL)
1167 {
1168 retval = ext_coms;
1169 ext_coms = retval->next;
1170
1171 sh_ext_tas_free (&(retval->tas));
1172
[215]1173 if (retval->filter)
1174 sh_filter_free (retval->filter);
[1]1175
1176 SH_FREE(retval);
1177
1178 }
1179
1180 SL_RETURN (0, _("sh_ext_cleanup"));
1181}
1182
1183/*
[164]1184 * -- explicitely close a command
1185 */
1186int sh_ext_close_command (const char * str)
1187{
1188 (void) str;
1189 if (ext_coms == NULL || ext_failed == (-1))
1190 return (-1);
1191 ext_failed = (-1);
1192 return 0;
1193}
1194
1195/*
[1]1196 * -- add keywords to the OR filter
1197 */
[22]1198int sh_ext_add_or (const char * str)
[1]1199{
1200 if (ext_coms == NULL || ext_failed == (-1))
1201 return (-1);
[215]1202 if (ext_coms->filter == NULL)
1203 ext_coms->filter = sh_filter_alloc();
1204 return (sh_filter_add(str, ext_coms->filter, SH_FILT_OR));
[1]1205}
1206
1207/*
1208 * -- add keywords to the AND filter
1209 */
[22]1210int sh_ext_add_and (const char * str)
[1]1211{
1212 if (ext_coms == NULL || ext_failed == (-1))
1213 return (-1);
[215]1214 if (ext_coms->filter == NULL)
1215 ext_coms->filter = sh_filter_alloc();
1216 return (sh_filter_add(str, ext_coms->filter, SH_FILT_AND));
[1]1217}
1218
1219/*
1220 * -- add keywords to the NOT filter
1221 */
[22]1222int sh_ext_add_not (const char * str)
[1]1223{
1224 if (ext_coms == NULL || ext_failed == (-1))
1225 return (-1);
[215]1226 if (ext_coms->filter == NULL)
1227 ext_coms->filter = sh_filter_alloc();
1228 return (sh_filter_add(str, ext_coms->filter, SH_FILT_NOT));
[1]1229}
1230
1231/*
1232 * -- add keywords to the CL argument list
1233 */
[22]1234int sh_ext_add_argv (const char * str)
[1]1235{
1236 if (ext_coms == NULL || ext_failed == (-1))
1237 return (-1);
1238 return (sh_ext_add (str, &(ext_coms->tas.argc), ext_coms->tas.argv));
1239}
1240
1241/*
1242 * -- add a path to the environment
1243 */
[22]1244int sh_ext_add_default (const char * dummy)
[1]1245{
[22]1246 char * p = NULL;
[1]1247 int i;
[132]1248 char dir[SH_PATHBUF];
[1]1249
1250 SL_ENTER(_("sh_ext_add_default"));
1251 if (dummy[0] == 'n' || dummy[0] == 'N' ||
1252 dummy[0] == 'f' || dummy[0] == 'F' || dummy[0] == '0')
1253 {
1254 SL_RETURN(0, _("sh_ext_add_default"));
1255 }
[132]1256 p = sh_unix_getUIDdir (SH_ERR_ERR, (uid_t) ext_coms->tas.run_user_uid,
1257 dir, sizeof(dir));
[1]1258 if (p)
1259 (void) sh_ext_add_envv (_("HOME"), p);
1260 (void) sh_ext_add_envv (_("SHELL"), _("/bin/sh"));
[211]1261 (void) sh_ext_add_envv (_("PATH"), _("/sbin:/bin:/usr/sbin:/usr/bin"));
1262 (void) sh_ext_add_envv (_("IFS"), " \n\t");
[1]1263 i = (p == NULL ? (-1) : 0);
1264 SL_RETURN(i, _("sh_ext_add_default"));
1265}
1266
1267/*
1268 * -- add an environment variable
1269 */
[22]1270int sh_ext_add_environ (const char * str)
[1]1271{
1272 int i;
[49]1273
[1]1274 SL_ENTER(_("sh_ext_add_environ"));
1275 i = sh_ext_add_envv (NULL, str);
1276 SL_RETURN(i, _("sh_ext_add_environ"));
1277}
1278
1279/*
1280 * -- set deadtime
1281 */
[22]1282int sh_ext_deadtime (const char * str)
[1]1283{
1284 long deadtime = 0;
1285 char * tail = NULL;
1286
1287 SL_ENTER(_("sh_ext_deadtime"));
1288
1289 if (ext_coms == NULL || ext_failed == (-1) || str == NULL)
1290 {
[170]1291 SL_RETURN (-1, _("sh_ext_deadtime"));
[1]1292 }
1293 deadtime = strtol(str, &tail, 10);
1294 if (tail == str || deadtime < 0 || deadtime == LONG_MAX)
1295 {
[170]1296 SL_RETURN (-1, _("sh_ext_deadtime"));
[1]1297 }
1298
1299 ext_coms->deadtime = (time_t) deadtime;
[170]1300 SL_RETURN (0, _("sh_ext_deadtime"));
[1]1301}
1302
1303/*
1304 * -- define type
1305 */
[22]1306int sh_ext_type (const char * str)
[1]1307{
1308 SL_ENTER(_("sh_ext_type"));
1309
1310 if (ext_coms == NULL || ext_failed == (-1) || str == NULL)
1311 {
1312 SL_RETURN((-1), _("sh_ext_type"));
1313 }
1314
1315 if (strlen(str) != 3)
1316 {
1317 SL_RETURN((-1), _("sh_ext_type"));
1318 }
1319
1320 set3(ext_coms->type, str[0], str[1], str[2]);
1321
1322 if (str[0] == 'l' && str[1] == 'o' && str[2] == 'g')
1323 ext_coms->tas.rw = 'w';
1324 else if (str[0] == 's' && str[1] == 'r' && str[2] == 'v')
1325 ext_coms->tas.rw = 'w';
1326 else if (str[0] == 'm' && str[1] == 'o' && str[2] == 'n')
1327 ext_coms->tas.rw = 'r';
1328 else
1329 {
1330 SL_RETURN((-1), _("sh_ext_type"));
1331 }
1332
1333 SL_RETURN(0, _("sh_ext_type"));
1334}
1335
1336
1337
1338/*
1339 * -- define checksum
1340 */
[22]1341int sh_ext_checksum (const char * str)
[1]1342{
1343 SL_ENTER(_("sh_ext_checksum"));
1344 if (ext_coms == NULL || ext_failed == (-1) || str == NULL)
1345 {
1346 SL_RETURN((-1), _("sh_ext_checksum"));
1347 }
1348
1349 if (sl_strlen(str) != KEY_LEN)
1350 {
1351 SL_RETURN((-1), _("sh_ext_checksum"));
1352 }
1353
1354 (void) sl_strlcpy (ext_coms->tas.checksum, str, KEY_LEN+1);
1355
1356 SL_RETURN((0), _("sh_ext_checksum"));
1357}
1358
1359/*
1360 * -- choose privileges
1361 */
[22]1362int sh_ext_priv (const char * c)
[1]1363{
1364
1365 uid_t me_uid;
1366 gid_t me_gid;
1367
1368 SL_ENTER(_("sh_ext_priv"));
1369 if (0 == sh_ext_uid (c, &me_uid, &me_gid))
1370 {
1371 ext_coms->tas.run_user_uid = me_uid;
1372 ext_coms->tas.run_user_gid = me_gid;
1373 if (me_uid != (uid_t) 0)
1374 ext_coms->tas.privileged = 0;
1375 SL_RETURN((0), _("sh_ext_priv"));
1376 }
1377
1378 SL_RETURN (-1, _("sh_ext_priv"));
1379}
1380
1381
1382
1383
1384/*
1385 * -- check filters
1386 */
1387static int sh_ext_filter (char * message, sh_com_t * task)
1388{
1389 time_t now_time;
1390
1391 SL_ENTER(_("sh_ext_filter"));
1392
[215]1393 if (task->filter)
[1]1394 {
[215]1395 if (0 != sh_filter_filter (message, task->filter))
[1]1396 {
[215]1397 SL_RETURN ((-1), _("sh_ext_filter"));
[1]1398 }
1399 }
1400
[215]1401 /* Filter passed, check deadtime */
[1]1402
[215]1403 if (task->deadtime != (time_t) 0)
[1]1404 {
1405 now_time = time (NULL);
1406
1407 if (task->last_run == (time_t) 0)
1408 {
1409 task->last_run = now_time;
1410 }
1411 else if ((time_t)(now_time-task->last_run) < task->deadtime)
1412 {
1413 SL_RETURN ((-1), _("sh_ext_filter"));
1414 }
1415 else
1416 {
1417 task->last_run = now_time;
1418 }
1419 }
1420
1421 SL_RETURN ((0), _("sh_ext_filter"));
1422}
1423
1424
1425
1426/*
1427 * -- execute external script/program
1428 */
1429int sh_ext_execute (char t1, char t2, char t3, /*@null@*/char * message,
1430 size_t msg_siz)
1431{
1432 int caperr;
1433 sh_com_t * listval = ext_coms;
1434 int status = 0;
1435 char * tmp;
[132]1436 char errbuf[SH_ERRBUF_SIZE];
[1]1437
1438 static int some_error = 0;
1439
1440 struct sigaction new_act;
1441 struct sigaction old_act;
1442
1443 SL_ENTER(_("sh_ext_execute"));
1444
1445 PDBG_OPEN;
1446
1447 if (listval == NULL || message == NULL)
1448 {
1449 SL_RETURN ((-1), _("sh_ext_execute"));
1450 }
1451
1452 PDBG(-1);
1453
1454 if (msg_siz == 0)
1455 msg_siz = sl_strlen(message);
1456
1457
1458 /* ignore SIGPIPE (instead get EPIPE if connection is closed)
1459 */
1460 new_act.sa_handler = SIG_IGN;
1461 (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &new_act, &old_act);
1462
1463 while (listval != NULL)
1464 {
[212]1465 PDBG_OPEN;
[1]1466 PDBG(-2);
1467 if (t1 == listval->type[0] &&
1468 t2 == listval->type[1] &&
1469 t3 == listval->type[2] &&
1470 0 == sh_ext_filter (message, listval))
1471 {
1472 PDBG(-3);
1473
1474 if (0 != (caperr = sl_get_cap_sub()))
1475 {
1476 sh_error_handle((-1), FIL__, __LINE__, caperr, MSG_E_SUBGEN,
[132]1477 sh_error_message (caperr, errbuf, sizeof(errbuf)),
[1]1478 _("sl_get_cap_sub"));
1479 }
1480 if (0 == sh_ext_popen (&(listval->tas)))
1481 {
1482 PDBG_OPEN;
1483 PDBG(-4);
1484 if (NULL != listval->tas.pipe && listval->tas.rw == 'w')
1485 {
1486 PDBG(-5);
1487 if (message != NULL)
1488 {
1489 PDBG(-6);
1490 status = (int) write (listval->tas.pipeFD,
1491 message, msg_siz);
1492 if (status >= 0)
1493 status = (int) write (listval->tas.pipeFD, "\n", 1);
1494 }
1495 PDBG_D(status);
1496 if (status >= 0)
1497 status = (int) write (listval->tas.pipeFD, "[", 1);
1498 PDBG_D(status);
1499 if (status >= 0)
1500 status = (int) write (listval->tas.pipeFD, "E", 1);
1501 PDBG_D(status);
1502 if (status >= 0)
1503 status = (int) write (listval->tas.pipeFD, "O", 1);
1504 PDBG_D(status);
1505 if (status >= 0)
1506 status = (int) write (listval->tas.pipeFD, "F", 1);
1507 PDBG_D(status);
1508 if (status >= 0)
1509 status = (int) write (listval->tas.pipeFD, "]", 1);
1510 PDBG_D(status);
1511 if (status >= 0)
1512 status = (int) write (listval->tas.pipeFD, "\n", 1);
1513 PDBG_D(status);
1514 if (status >= 0)
1515 {
1516 some_error = 0;
1517 }
1518 if ((status < 0) && (some_error == 0))
1519 {
1520 some_error = 1;
1521 PDBG_S("some error");
1522 PDBG_D(status);
1523 tmp = sh_util_safe_name (listval->tas.command);
1524
1525 if (tmp)
1526 {
1527 if (listval->tas.privileged == 0 &&
1528 (0 == getuid() || 0 != sl_is_suid()) )
1529 sh_error_handle((-1), FIL__, __LINE__, 0,
1530 MSG_NOEXEC,
1531 (UID_CAST) listval->tas.run_user_uid,
1532 tmp);
1533 else
1534 sh_error_handle((-1), FIL__, __LINE__, 0,
1535 MSG_NOEXEC,
1536 (UID_CAST) getuid(), tmp);
1537
1538 SH_FREE(tmp);
1539 }
1540
1541 }
1542 PDBG(-7);
1543 (void) fflush(listval->tas.pipe);
1544 }
1545 PDBG(-8);
1546 (void) sh_ext_pclose(&(listval->tas));
1547 }
1548 else
1549 {
1550 PDBG_OPEN;
1551 PDBG_S("0 != sh_ext_popen()");
1552 }
1553 if (0 != (caperr = sl_drop_cap_sub()))
1554 {
1555 sh_error_handle((-1), FIL__, __LINE__, caperr, MSG_E_SUBGEN,
[132]1556 sh_error_message (caperr, errbuf, sizeof(errbuf)),
[1]1557 _("sl_drop_cap_sub"));
1558 }
1559
1560 }
1561 listval = listval->next;
1562 }
1563 PDBG_OPEN;
1564 PDBG_S("no more commands");
1565
1566 /* restore old signal handler
1567 */
1568 (void) retry_sigaction (FIL__, __LINE__, SIGPIPE, &old_act, NULL);
1569 PDBG_S("return");
1570 PDBG_CLOSE;
1571
1572 SL_RETURN ((0), _("sh_ext_execute"));
1573}
1574
1575
1576/* #if defined(WITH_EXTERNAL) */
1577#endif
Note: See TracBrowser for help on using the repository browser.