Blame


1 6b5c4000 2026-03-02 rsadowski /* $OpenBSD: check_script.c,v 1.23 2026/03/02 19:28:01 rsadowski Exp $ */
2 292100ef 2007-05-29 reyk
3 292100ef 2007-05-29 reyk /*
4 dc2f787f 2014-06-25 reyk * Copyright (c) 2007 - 2014 Reyk Floeter <reyk@openbsd.org>
5 292100ef 2007-05-29 reyk *
6 292100ef 2007-05-29 reyk * Permission to use, copy, modify, and distribute this software for any
7 292100ef 2007-05-29 reyk * purpose with or without fee is hereby granted, provided that the above
8 292100ef 2007-05-29 reyk * copyright notice and this permission notice appear in all copies.
9 292100ef 2007-05-29 reyk *
10 292100ef 2007-05-29 reyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 292100ef 2007-05-29 reyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 292100ef 2007-05-29 reyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 292100ef 2007-05-29 reyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 292100ef 2007-05-29 reyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 292100ef 2007-05-29 reyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 292100ef 2007-05-29 reyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 292100ef 2007-05-29 reyk */
18 292100ef 2007-05-29 reyk
19 292100ef 2007-05-29 reyk #include <sys/wait.h>
20 d93c36af 2015-01-22 reyk #include <sys/time.h>
21 292100ef 2007-05-29 reyk
22 292100ef 2007-05-29 reyk #include <errno.h>
23 292100ef 2007-05-29 reyk #include <unistd.h>
24 292100ef 2007-05-29 reyk #include <string.h>
25 292100ef 2007-05-29 reyk #include <stdlib.h>
26 292100ef 2007-05-29 reyk #include <signal.h>
27 292100ef 2007-05-29 reyk #include <pwd.h>
28 292100ef 2007-05-29 reyk
29 6d0767ae 2007-12-07 reyk #include "relayd.h"
30 6b5c4000 2026-03-02 rsadowski #include "log.h"
31 292100ef 2007-05-29 reyk
32 292100ef 2007-05-29 reyk void script_sig_alarm(int);
33 292100ef 2007-05-29 reyk
34 dbef7d4f 2011-05-09 reyk pid_t child = -1;
35 292100ef 2007-05-29 reyk
36 292100ef 2007-05-29 reyk void
37 dbef7d4f 2011-05-09 reyk check_script(struct relayd *env, struct host *host)
38 292100ef 2007-05-29 reyk {
39 292100ef 2007-05-29 reyk struct ctl_script scr;
40 1ffcf252 2011-05-26 reyk struct table *table;
41 292100ef 2007-05-29 reyk
42 615c8bd8 2021-02-22 jmatthew if ((host->flags & (F_CHECK_SENT|F_CHECK_DONE)) == F_CHECK_SENT)
43 615c8bd8 2021-02-22 jmatthew return;
44 615c8bd8 2021-02-22 jmatthew
45 1ffcf252 2011-05-26 reyk if ((table = table_find(env, host->conf.tableid)) == NULL)
46 09e53fee 2017-05-28 benno fatalx("%s: invalid table id", __func__);
47 1ffcf252 2011-05-26 reyk
48 292100ef 2007-05-29 reyk host->last_up = host->up;
49 292100ef 2007-05-29 reyk host->flags &= ~(F_CHECK_SENT|F_CHECK_DONE);
50 292100ef 2007-05-29 reyk
51 292100ef 2007-05-29 reyk scr.host = host->conf.id;
52 a6ecc53f 2014-04-20 reyk if ((strlcpy(scr.name, host->conf.name,sizeof(scr.name)) >=
53 a6ecc53f 2014-04-20 reyk sizeof(scr.name)) ||
54 a6ecc53f 2014-04-20 reyk (strlcpy(scr.path, table->conf.path, sizeof(scr.path)) >=
55 a6ecc53f 2014-04-20 reyk sizeof(scr.path)))
56 a6ecc53f 2014-04-20 reyk fatalx("invalid script path");
57 1ffcf252 2011-05-26 reyk memcpy(&scr.timeout, &table->conf.timeout, sizeof(scr.timeout));
58 1ffcf252 2011-05-26 reyk
59 615c8bd8 2021-02-22 jmatthew if (proc_compose(env->sc_ps, PROC_PARENT, IMSG_SCRIPT, &scr,
60 615c8bd8 2021-02-22 jmatthew sizeof(scr)) == 0)
61 615c8bd8 2021-02-22 jmatthew host->flags |= F_CHECK_SENT;
62 292100ef 2007-05-29 reyk }
63 292100ef 2007-05-29 reyk
64 292100ef 2007-05-29 reyk void
65 6d0767ae 2007-12-07 reyk script_done(struct relayd *env, struct ctl_script *scr)
66 292100ef 2007-05-29 reyk {
67 292100ef 2007-05-29 reyk struct host *host;
68 292100ef 2007-05-29 reyk
69 292100ef 2007-05-29 reyk if ((host = host_find(env, scr->host)) == NULL)
70 09e53fee 2017-05-28 benno fatalx("%s: invalid host id", __func__);
71 292100ef 2007-05-29 reyk
72 292100ef 2007-05-29 reyk if (scr->retval < 0)
73 292100ef 2007-05-29 reyk host->up = HOST_UNKNOWN;
74 292100ef 2007-05-29 reyk else if (scr->retval == 0)
75 292100ef 2007-05-29 reyk host->up = HOST_DOWN;
76 292100ef 2007-05-29 reyk else
77 292100ef 2007-05-29 reyk host->up = HOST_UP;
78 292100ef 2007-05-29 reyk host->flags |= F_CHECK_DONE;
79 292100ef 2007-05-29 reyk
80 292100ef 2007-05-29 reyk hce_notify_done(host, host->up == HOST_UP ?
81 b2665266 2008-12-05 reyk HCE_SCRIPT_OK : HCE_SCRIPT_FAIL);
82 292100ef 2007-05-29 reyk }
83 292100ef 2007-05-29 reyk
84 292100ef 2007-05-29 reyk void
85 292100ef 2007-05-29 reyk script_sig_alarm(int sig)
86 292100ef 2007-05-29 reyk {
87 581a3430 2007-10-13 deraadt int save_errno = errno;
88 581a3430 2007-10-13 deraadt
89 292100ef 2007-05-29 reyk if (child != -1)
90 292100ef 2007-05-29 reyk kill(child, SIGKILL);
91 581a3430 2007-10-13 deraadt errno = save_errno;
92 292100ef 2007-05-29 reyk }
93 292100ef 2007-05-29 reyk
94 292100ef 2007-05-29 reyk int
95 6d0767ae 2007-12-07 reyk script_exec(struct relayd *env, struct ctl_script *scr)
96 292100ef 2007-05-29 reyk {
97 292100ef 2007-05-29 reyk int status = 0, ret = 0;
98 292100ef 2007-05-29 reyk sig_t save_quit, save_int, save_chld;
99 292100ef 2007-05-29 reyk struct itimerval it;
100 292100ef 2007-05-29 reyk struct timeval *tv;
101 292100ef 2007-05-29 reyk const char *file, *arg;
102 292100ef 2007-05-29 reyk struct passwd *pw;
103 292100ef 2007-05-29 reyk
104 58fc320c 2016-09-02 reyk if ((env->sc_conf.flags & F_SCRIPT) == 0) {
105 12566ac9 2011-05-26 reyk log_warnx("%s: script disabled", __func__);
106 12566ac9 2011-05-26 reyk return (-1);
107 12566ac9 2011-05-26 reyk }
108 12566ac9 2011-05-26 reyk
109 1ffcf252 2011-05-26 reyk DPRINTF("%s: running script %s, host %s",
110 1ffcf252 2011-05-26 reyk __func__, scr->path, scr->name);
111 292100ef 2007-05-29 reyk
112 1ffcf252 2011-05-26 reyk arg = scr->name;
113 1ffcf252 2011-05-26 reyk file = scr->path;
114 1ffcf252 2011-05-26 reyk tv = &scr->timeout;
115 292100ef 2007-05-29 reyk
116 292100ef 2007-05-29 reyk save_quit = signal(SIGQUIT, SIG_IGN);
117 292100ef 2007-05-29 reyk save_int = signal(SIGINT, SIG_IGN);
118 292100ef 2007-05-29 reyk save_chld = signal(SIGCHLD, SIG_DFL);
119 292100ef 2007-05-29 reyk
120 292100ef 2007-05-29 reyk switch (child = fork()) {
121 292100ef 2007-05-29 reyk case -1:
122 292100ef 2007-05-29 reyk ret = -1;
123 292100ef 2007-05-29 reyk goto done;
124 292100ef 2007-05-29 reyk case 0:
125 292100ef 2007-05-29 reyk signal(SIGQUIT, SIG_DFL);
126 292100ef 2007-05-29 reyk signal(SIGINT, SIG_DFL);
127 292100ef 2007-05-29 reyk signal(SIGCHLD, SIG_DFL);
128 292100ef 2007-05-29 reyk
129 6d0767ae 2007-12-07 reyk if ((pw = getpwnam(RELAYD_USER)) == NULL)
130 09e53fee 2017-05-28 benno fatal("%s: getpwnam", __func__);
131 292100ef 2007-05-29 reyk if (chdir("/") == -1)
132 09e53fee 2017-05-28 benno fatal("%s: chdir(\"/\")", __func__);
133 292100ef 2007-05-29 reyk if (setgroups(1, &pw->pw_gid) ||
134 292100ef 2007-05-29 reyk setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
135 292100ef 2007-05-29 reyk setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
136 09e53fee 2017-05-28 benno fatal("%s: can't drop privileges", __func__);
137 292100ef 2007-05-29 reyk
138 6e8f642d 2009-04-17 reyk /*
139 6e8f642d 2009-04-17 reyk * close fds before executing an external program, to
140 6e8f642d 2009-04-17 reyk * prevent access to internal fds, eg. IMSG connections
141 6e8f642d 2009-04-17 reyk * of internal processes.
142 6e8f642d 2009-04-17 reyk */
143 6e8f642d 2009-04-17 reyk closefrom(STDERR_FILENO + 1);
144 6e8f642d 2009-04-17 reyk
145 292100ef 2007-05-29 reyk execlp(file, file, arg, (char *)NULL);
146 292100ef 2007-05-29 reyk _exit(0);
147 292100ef 2007-05-29 reyk break;
148 292100ef 2007-05-29 reyk default:
149 292100ef 2007-05-29 reyk /* Kill the process after a timeout */
150 292100ef 2007-05-29 reyk signal(SIGALRM, script_sig_alarm);
151 292100ef 2007-05-29 reyk bzero(&it, sizeof(it));
152 292100ef 2007-05-29 reyk bcopy(tv, &it.it_value, sizeof(it.it_value));
153 292100ef 2007-05-29 reyk setitimer(ITIMER_REAL, &it, NULL);
154 292100ef 2007-05-29 reyk
155 292100ef 2007-05-29 reyk waitpid(child, &status, 0);
156 292100ef 2007-05-29 reyk break;
157 292100ef 2007-05-29 reyk }
158 292100ef 2007-05-29 reyk
159 292100ef 2007-05-29 reyk switch (ret) {
160 292100ef 2007-05-29 reyk case -1:
161 292100ef 2007-05-29 reyk ret = -1;
162 292100ef 2007-05-29 reyk break;
163 292100ef 2007-05-29 reyk default:
164 292100ef 2007-05-29 reyk if (WIFEXITED(status))
165 292100ef 2007-05-29 reyk ret = WEXITSTATUS(status);
166 292100ef 2007-05-29 reyk else
167 da5cdd0a 2011-02-28 sthen ret = 0;
168 292100ef 2007-05-29 reyk }
169 292100ef 2007-05-29 reyk
170 292100ef 2007-05-29 reyk done:
171 292100ef 2007-05-29 reyk /* Disable the process timeout timer */
172 292100ef 2007-05-29 reyk bzero(&it, sizeof(it));
173 292100ef 2007-05-29 reyk setitimer(ITIMER_REAL, &it, NULL);
174 292100ef 2007-05-29 reyk child = -1;
175 292100ef 2007-05-29 reyk
176 292100ef 2007-05-29 reyk signal(SIGQUIT, save_quit);
177 292100ef 2007-05-29 reyk signal(SIGINT, save_int);
178 292100ef 2007-05-29 reyk signal(SIGCHLD, save_chld);
179 292100ef 2007-05-29 reyk signal(SIGALRM, SIG_DFL);
180 292100ef 2007-05-29 reyk
181 292100ef 2007-05-29 reyk return (ret);
182 292100ef 2007-05-29 reyk }