The usual application is to confine security-privileged
applications to some sort of gatekeeper program, which can then hand
state to a less privileged one. The technique pastes several programs
together using execs, or possibly a combination of forks and
execs. The programs are all named on one command line. Each program
performs some function and (if successful) runs
exec(2)
on the rest of its command line.
Bernstein's rblsmtpd package is a
prototypical example. It serves to look up a host in the antispam DNS
zone of the Mail Abuse Prevention System. It does this by doing a DNS
query on the IP address passed into it in the
TCPREMOTEIP environment variable. If the query is
successful, then rblsmtpd runs its own SMTP
that discards the mail. Otherwise the remaining command-line arguments
are presumed to constitute a mail transport agent that knows the SMTP
protocol, and are handed to
exec(2)
to be run.
Another example can be found in Bernstein's
qmail package. It contains a program called
condredirect. The first parameter is an
email address, and the remainder a gatekeeper program and
arguments. condredirect forks and execs the
gatekeeper with its arguments. If the gatekeeper exits successfully,
condredirect forwards the email
pending on stdin to the specified email address. In this case,
opposite to that of rblsmtpd, the security
decision is made by the child; this case is a bit more like a
classical shellout.
A more elaborate example is the qmail
POP3 server. It consists of three programs,
qmail-popup,
checkpassword, and
qmail-pop3d.
Checkpassword comes from a separate package
cleverly called checkpassword, and
unsurprisingly it checks the password. The POP3 protocol has an
authentication phase and mailbox phase; once you enter the mailbox
phase you cannot go back to the authentication phase. This is a
perfect application for Bernstein chaining.
The first parameter of qmail-popup is
the hostname to use in the POP3 prompts. The rest of its parameters
are forked and passed to
exec(2),
after the POP3 username and password have been fetched. If the program
returns failure, the password must be wrong, so
qmail-popup reports that and waits for a
different password. Otherwise, the program is presumed to have
finished the POP3 conversation, so
qmail-popup exits.
Bernstein chaining is useful for situations in which the
application needs setuid or setgid privileges to initialize a
connection, or to acquire some credential, and then drop those
privileges so that following code does not have to be trusted.
Following the exec, the child program cannot set its real user ID back
to root. It's also more flexible than a single process, because you
can modify the behavior of the system by inserting another program
into the chain.