3 * Privilege separation communication protocol
5 * (c) 2008 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Trivial IP Encryption (TrIPE).
12 * TrIPE is free software: you can redistribute it and/or modify it under
13 * the terms of the GNU General Public License as published by the Free
14 * Software Foundation; either version 3 of the License, or (at your
15 * option) any later version.
17 * TrIPE is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * You should have received a copy of the GNU General Public License
23 * along with TrIPE. If not, see <https://www.gnu.org/licenses/>.
26 /*----- Header files ------------------------------------------------------*/
31 /*----- Static variables --------------------------------------------------*/
33 static pid_t kid = -1;
36 /*----- Fetching a tunnel file descriptor ---------------------------------*/
38 /* --- @ps_tunfd@ --- *
40 * Arguments: @const tunnel_ops *tops@ = pointer to tunnel operations
41 * @char **ifn@ = where to put the interface name
43 * Returns: The file descriptor, or @-1@ on error.
45 * Use: Fetches a file descriptor for a tunnel driver.
48 int ps_tunfd(const tunnel_ops *tops, char **ifn)
56 a_warn("PRIVSEP", "helper-died", A_END);
60 "privsep: requesting descriptor for %s tunnel",
62 if (pc_putuint(PS_TUNRQ) || pc_putstring(tops->name)) {
63 a_warn("PRIVSEP", "helper-write-error", "?ERRNO", A_END);
67 n = fdpass_recv(pc_fd, &fd, &code, sizeof(code));
68 if (n < 0) goto readlose;
69 if (n < sizeof(code)) {
70 a_warn("PRIVSEP", "helper-short-read", A_END);
76 a_warn("PRIVSEP", "no-fd-from-helper", A_END);
79 if (pc_getstring(&d)) { close(fd); goto readlose; }
80 *ifn = xstrdup(d.buf);
82 "privsep: received winning descriptor for %s",
86 if (pc_geterr(&errno)) goto readlose;
87 T( trace(T_PRIVSEP, "privsep: helper lost: %s", strerror(errno)); )
92 if (pc_getuint(&code) || pc_getstring(&d)) goto readlose;
93 trace(code, "%s", d.buf);
98 if (pc_getstring(&d)) goto readlose;
99 a_warn("*%s", d.buf, A_END);
103 a_warn("PRIVSEP", "unknown-response-code", "%u", code, A_END);
112 a_warn("PRIVSEP", "helper-read-error", "?ERRNO", A_END);
120 /*----- Main code ---------------------------------------------------------*/
124 * Arguments: @int sig@ = signal number (always @SIGCHLD@; ignored)
128 * Use: Notices and reports child process death.
131 static void reap(int sig, void *p)
137 k = waitpid(-1, &st, WNOHANG);
143 a_warn("SERVER", "waitpid-error", "?ERRNO", A_END);
152 a_warn("PRIVSEP", "child-exited", "%d", WEXITSTATUS(st), A_END);
153 else if (WIFSIGNALED(st))
154 a_warn("PRIVSEP", "child-killed", "%d", WTERMSIG(st), A_END);
156 a_warn("PRIVSEP", "child-died", "%d", st, A_END);
162 /* --- @ps_split@ --- *
164 * Arguments: @int detachp@ = whether to detach the child from its terminal
168 * Use: Separates off the privileged tunnel-opening service from the
169 * rest of the server.
172 void ps_split(int detachp)
179 if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd)) {
181 "failed to create socket pair for privilege separation: %s",
184 helper = getenv("TRIPE_PRIVHELPER");
185 if (!helper) helper = PRIVSEP_HELPER;
186 fdflags(fd[0], 0, 0, FD_CLOEXEC, FD_CLOEXEC);
187 fdflags(fd[1], 0, 0, FD_CLOEXEC, FD_CLOEXEC);
188 sig_add(&sig_chld, SIGCHLD, reap, 0);
191 signal(SIGCHLD, SIG_DFL);
192 if (detachp) detachtty();
194 md[0].cur = fd[0]; md[0].want = STDIN_FILENO;
195 if (mdup(md, 1)) goto lose;
196 execl(helper, helper, (char *)0);
198 fprintf(stderr, "helper: failed to run helper: %s\n", strerror(errno));
201 T( trace(T_PRIVSEP, "privsep: forked child successfully"); )
206 /* --- @ps_quit@ --- *
212 * Use: Detaches from the helper process.
215 void ps_quit(void) { if (pc_fd != -1) close(pc_fd); }
217 /*----- That's all, folks -------------------------------------------------*/