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
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * TrIPE is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with TrIPE; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 /*----- Header files ------------------------------------------------------*/
32 /*----- Static variables --------------------------------------------------*/
34 static pid_t kid
= -1;
37 /*----- Fetching a tunnel file descriptor ---------------------------------*/
39 /* --- @ps_tunfd@ --- *
41 * Arguments: @const tunnel_ops *tops@ = pointer to tunnel operations
42 * @char **ifn@ = where to put the interface name
44 * Returns: The file descriptor, or @-1@ on error.
46 * Use: Fetches a file descriptor for a tunnel driver.
49 int ps_tunfd(const tunnel_ops
*tops
, char **ifn
)
57 a_warn("PRIVSEP", "helper-died", A_END
);
61 "privsep: requesting descriptor for %s tunnel",
63 if (pc_putuint(PS_TUNRQ
) || pc_putstring(tops
->name
)) {
64 a_warn("PRIVSEP", "helper-write-error", "?ERRNO", A_END
);
68 n
= fdpass_recv(pc_fd
, &fd
, &code
, sizeof(code
));
69 if (n
< 0) goto readlose
;
70 if (n
< sizeof(code
)) {
71 a_warn("PRIVSEP", "helper-short-read", A_END
);
77 a_warn("PRIVSEP", "no-fd-from-helper", A_END
);
80 if (pc_getstring(&d
)) { close(fd
); goto readlose
; }
81 *ifn
= xstrdup(d
.buf
);
83 "privsep: received winning descriptor for %s",
87 if (pc_geterr(&errno
)) goto readlose
;
88 T( trace(T_PRIVSEP
, "privsep: helper lost: %s", strerror(errno
)); )
93 if (pc_getuint(&code
) || pc_getstring(&d
)) goto readlose
;
94 trace(code
, "%s", d
.buf
);
99 if (pc_getstring(&d
)) goto readlose
;
100 a_warn("*%s", d
.buf
, A_END
);
104 a_warn("PRIVSEP", "unknown-response-code", "%u", code
, A_END
);
113 a_warn("PRIVSEP", "helper-read-error", "?ERRNO", A_END
);
121 /*----- Main code ---------------------------------------------------------*/
125 * Arguments: @int sig@ = signal number (always @SIGCHLD@; ignored)
129 * Use: Notices and reports child process death.
132 static void reap(int sig
, void *p
)
138 k
= waitpid(-1, &st
, WNOHANG
);
144 a_warn("SERVER", "waitpid-error", "?ERRNO", A_END
);
153 a_warn("PRIVSEP", "child-exited", "%d", WEXITSTATUS(st
), A_END
);
154 else if (WIFSIGNALED(st
))
155 a_warn("PRIVSEP", "child-killed", "%d", WTERMSIG(st
), A_END
);
157 a_warn("PRIVSEP", "child-died", "%d", st
, A_END
);
163 /* --- @ps_split@ --- *
165 * Arguments: @int detachp@ = whether to detach the child from its terminal
169 * Use: Separates off the privileged tunnel-opening service from the
170 * rest of the server.
173 void ps_split(int detachp
)
180 if (socketpair(PF_UNIX
, SOCK_STREAM
, 0, fd
)) {
182 "failed to create socket pair for privilege separation: %s",
185 helper
= getenv("TRIPE_PRIVHELPER");
186 if (!helper
) helper
= PRIVSEP_HELPER
;
187 fdflags(fd
[0], 0, 0, FD_CLOEXEC
, FD_CLOEXEC
);
188 fdflags(fd
[1], 0, 0, FD_CLOEXEC
, FD_CLOEXEC
);
189 sig_add(&sig_chld
, SIGCHLD
, reap
, 0);
192 signal(SIGCHLD
, SIG_DFL
);
193 if (detachp
) detachtty();
195 md
[0].cur
= fd
[0]; md
[0].want
= STDIN_FILENO
;
196 if (mdup(md
, 1)) goto lose
;
197 execl(helper
, helper
, (char *)0);
199 fprintf(stderr
, "helper: failed to run helper: %s\n", strerror(errno
));
202 T( trace(T_PRIVSEP
, "privsep: forked child successfully"); )
207 /* --- @ps_quit@ --- *
213 * Use: Detaches from the helper process.
216 void ps_quit(void) { if (pc_fd
!= -1) close(pc_fd
); }
218 /*----- That's all, folks -------------------------------------------------*/