source: trunk/src/sh_extern.c@ 584

Last change on this file since 584 was 583, checked in by katerina, 2 months ago

Fix for ticket #471 (autoreconf throws warnings/errors).

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