Re: sslio as a STARTTLS wrapper (was Re: sslio error description incomplete/wrong)
Scott Gifford <[email protected]>
| Newsgroups | gmane.comp.misc.pape.general |
|---|---|
| Message-ID | <[email protected]> |
Charlie Brady <[email protected]> writes: [...] > I'd like to do something very similar on the smtp port, with > smtpfront-qmail talking plain text smtp, until it sees a STARTTLS request. > This should be possible with just a little co-operation between sslio and > smtpfront-qmail. If sslio leaves smtpfront-qmail with stdin and stdout > connected to the network socket, and doesn't itself read from or write to > the network, smtpfront-qmail should be able to talk plain text SMTP to the > network, right? This seems like it should work. [...] > 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. 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. 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. Perhaps sslio can already do this; I haven't really looked into it. Another option I've considered is a standalone SSL daemon. 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. 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 awway. 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). 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. ----ScottG.