source: trunk/src/sh_extern.c@ 334

Last change on this file since 334 was 321, checked in by katerina, 14 years ago

Fix for ticket #240: The samhain_kmem kernel module should be loaded earlier

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