Re: sslio as a STARTTLS wrapper (was Re: sslio error description incomplete/wrong)
Charlie Brady <[email protected]>
| Newsgroups | gmane.comp.misc.pape.general |
|---|---|
| Message-ID | <Pine.LNX.4.44.0501061017080.16068-100000@e-smith.charlieb.ott.istop.com> |
On Thu, 6 Jan 2005, Scott Gifford wrote: > Charlie Brady <[email protected]> writes: > > [...] > > The main detail to flesh out is what form of IPC to use. Any suggestions? > > Any serious flaws in my thinking? > > A signal is the easiest way. That was my original thought, but see below. > You'd essentially have: > > smtpd: > process_starttls() > kill(SIGUSR1,getppid()); > dup2(SSLIN_FILENO,STDIN_FILENO); > dup2(SSLOUT_FILENO,STDOUT_FILENO); > > and that would be the entire change to the newly TLS-enabled server. It's my impression that SIGCONT is the only signal we can send across uid boundaries (presuming that both smtpd and sslio have changed uid), and then only if the processes are in the same session (as I think they would be here). I can't think of how we'd send two different messages ("take over", "die") with that one signal. But a single byte message over a pipe should do. > One concern that one of stunnel's authors (Brian Hatch?) had was that > starting up a brand new SSL-handling program wasted processing power, > since a lot of SSL's work is initialization. If we used a > tcpserver/tcpsvd replacement that natively understood SSL, it would > help with that concern. The operation would essentially be: > > /* Running as root */ > initialize_ssl(); > while(accept()) > fork() > child: > fork() > parent: > chroot("/nothing"); > setgid("nobody"); > setuid("nobody"); > be_ssl_tunnel(); > child: > setgid(g_option); > setuid(u_option); > exec(rest_of_args); > > The child would use IPC to ask the parent to begin SSL, as in your > proposal. More as in your proposal than mine, since this would require fd passing. > Perhaps sslio can already do this; I haven't really looked > into it. No, sslio doesn't duplicate tcpsvd/tcpserver's function. It's an SSL wrapper which supports privilege separation. > Another option I've considered is a standalone SSL daemon. There is William Baxter's ucspi-ssl, but that comes without any license, doesn't support privilege separation. > An application that wanted TLS would connect to this daemon via a UNIX > socket and send the network file descriptors, then receive back the > decrypted ends of an SSL connection: > > smtpd: > case STARTTLS: > s = socket(...) > connect(s, AF_UNIX, getenv(TLS_SOCKET),...) > sendfd(s,STDIN_FILENO); > sendfd(s,STDOUT_FILENO); > newfd = recvfd(s); > dup2(newfd, STDIN_FILENO); > newfd = recvfd(s); > dup2(newfd, STDIN_FILENO); > > This lets a single SSL daemon handle multiple services, which saves > resources. It's also the coolest of the solutions I've considered. Fd sending is unfamiliar territory for me (and most software it seems). The UNIX socket would be protected by file access permissions, right? > A third option I've used for a similar problem is to start up the TLS > proxy without executing the SMTP server. As soon as we receive any > command besides STARTTLS, we exec the SMTP server and send the first > command on FD 3 then close it; the SMTP server reads from FD 3 until > EOF, then switches to STDIN. If we receive STARTTLS, we start up an > encryption tunnel and then exec the SMTP server with the decrypted > ends of this. This only works if STARTTLS is the first command, but > in practice it always is. The advantage is that you don't have an SSL > server sitting around waiting for a signal; it just exits if it > doesn't see STARTTLS right away. This approach would mean that you need to have a TLS proxy which includes code which is a subset of any of the protocols which you want it to deal with (SMTP, IMAP, POP, etc). That's what stunnel currently does, and it's complexity I want to avoid. > My favorite of these is the tcpserver replacement that forks off an > SSL handler, which is activated by a signal. This has a very clean > interface, and the persistent daemon design may be more efficient with > SSL handling than a new copy of sslio every time (though I'll admit I > don't exactly understand all of SSL's performance characteristics). Nor is performance necessarily a big issue in most deployments. I can understand you wanting to avoid the SSL startup costs with each connection, but I don't have a picture of how signals and privilege separation would work here. I've also been trying to avoid mixing SSL code with existing stable well-tested applications. Avoiding any change to tcpserver/tcpsvd would be preferable (and in the case of tcpserver, required, if being able to distribute binaries matters). One more feature which is missing in all these proxy configurations is any mechanism to provide feedback to the mail daemon as to what SSL parameters was negotiated. In the fork/exec model which sslio has, this is necessary/deliberate, since the fork/exec occurs before any data is read from the network, so, e.g., an environment variable can't be set up for the the mail daemon describing the SSL negotiation outcome. This prevents, for instance, the mail daemon from adding a descriptive Received header. > I could probably find some time to help with a project like that, or > at least to test it since the coding should be fairly minimal. Thanks. Have you used Gerrit's ipsvd or Bruce's mailfront? Regards --- Charlie