1This file describes the design goals and the reasoning behind some of 2the design decisions for my tiny POP3 daemon, popa3d. 3 4 5 Why popa3d? 6 7There're lots of different POP3 servers -- with different feature 8sets, performance, and reliability. However, as far as I know, before 9I started the work on popa3d, there had been only one with security as 10one of its primary design goals: qmail-pop3d. Unfortunately, it would 11only work with qmail, and only with its new maildir format. While 12both qmail and maildirs do indeed have some advantages, a lot of 13people continue running other MTAs, and/or use the older mailbox 14format, for various reasons. Many of them need a POP3 server. 15 16 17 The design goals. 18 19Well, the goals themselves are obvious; they're probably the same for 20most other POP3 servers as well. It's their priority that differs. 21For popa3d, the goals are: 22 231. Security (to the extent that is possible with POP3 at all, of 24course). 25 262. Reliability (again, as limited by the mailbox format and the 27protocol). 28 293. RFC compliance (slightly relaxed to work with real-world POP3 30clients). 31 324. Performance (limited by the more important goals, above). 33 34Obviously, just like the comments indicate, none of the goals can be 35met completely, and balanced decisions need to be made. 36 37 38 Security. 39 40First, it is important that none of the popa3d users get a false sense 41of security just because it was the primary design goal. The POP3 42protocol transmits passwords in plaintext and thus, if you care about 43the security of your individual user accounts, should only be used 44either in trusted networks or tunneled over encrypted channels. 45There exist extensions to the protocol that are supposed to fix this 46problem. I am not supporting them yet, partly because this isn't 47going to fully fix the problem. In fact, APOP and the weaker defined 48SASL mechanisms such as CRAM-MD5 may potentially be even less secure 49than transmission of plaintext passwords because of the requirement 50that plaintext equivalents be stored on the server. 51 52It is also important to understand that nothing can be perfectly 53secure. I can make mistakes. While the design of popa3d makes it 54harder for those to turn into security holes, this is nevertheless 55still possible. 56 57Having that said, let's get to the security-critical design decisions. 58 59 60 Privilege management. 61 62Initially, popa3d is started as root to handle a connection. However, 63it does very little work as root: switching to less privileged UIDs, 64communication with child processes, and authentication information 65checks (which often involve accessing shadow or master.passwd files). 66 67The following privilege switches happen during a successful POP3 68session, with /etc/shadow authentication: 69 70 startup as root 71 | 72 ----------------- 73 |child |parent 74 v v 75 drop to user popa3d, still as root, 76 handle the AUTHORIZATION wait for and 77 state, write the results, - - > read the authentication 78 and exit information 79 | 80 ----------------- 81 |child |parent 82 v v 83 getspnam(3), crypt(3), wait for and 84 check, write the result, - - > read the authentication 85 and exit (to clean up) result 86 | 87 v 88 drop to the authenticated user, 89 handle the TRANSACTION state, 90 possibly UPDATE the mailbox, 91 and exit 92 93 94 Trust. 95 96No part of popa3d trusts any information obtained from external 97sources (that is, the data is never assumed to be of the expected 98format, and is treated as subject to authorization checks). This 99includes POP3 commands, mailbox contents, and even popa3d's own 100less-privileged child process for the AUTHORIZATION state handling. 101 102 103 DoS attacks. 104 105Just like with most other software, there exist ways to cause a Denial 106of Service, by supplying popa3d with an enormous amount of otherwise 107valid input. I am aware of the following attacks on popa3d itself: 108 1091. Connection flood. When running in the standalone mode, popa3d does 110quite a few checks to significantly reduce the impact of such attacks 111by limiting resource consumption (child processes and logging rate), 112while still providing full service for other source IP addresses and 113logging everything that might be important. However, when running 114from an inetd clone, the handling of these attacks is left up to your 115inetd and the kernel. 116 1172. Huge mailbox sizes, either in message count or bytes. There're 118limits in popa3d (see params.h) that are intended to prevent this 119attack from stopping the entire service. Depending on your disk and 120other quotas, it may still be possible to stop individual users from 121getting their mail. 122 123 124 Reliability. 125 126Quoting Dan Bernstein, "the mbox format ... is inherently unreliable". 127 128While popa3d, just like other mail software that deals with mailboxes, 129doesn't guarantee reliability over system crashes, it still makes 130sense to talk about its operation on an otherwise stable system. 131 132 133 Interaction with other MUAs. 134 135Similarly to cucipop (but unlike qpopper), popa3d works on the 136original mailbox file, without copying. However, unlike cucipop, 137popa3d is able to ensure that the mailbox doesn't get corrupted if 138another MUA modifies it during the POP session. Before each mailbox 139access, popa3d checks its timestamp and, if that has changed, 140determines if that is due to new mail that has just been delivered, or 141other changes made to the mailbox. In the latter case, the POP 142session is silently aborted (which doesn't violate the RFC). popa3d 143is careful to make sure the timestamp will change if the mailbox is 144written to, by keeping the lock for up to a second if necessary. 145 146 147 Mailbox access. 148 149Except for the total size and message count limits mentioned above 150(and you can disable even those), there're no other artificial limits 151on the mailbox contents. In particular, there're no line length 152limits; unlike with qmail-pop3d, lines don't even need to fit in the 153available memory. NUL bytes are allowed in messages as well. 154 155 156 Locking. 157 158Because of dropping to the user "completely" (that is, not even 159keeping a GID of mail like some other POP3 servers do), popa3d only 160uses fcntl(2) or flock(2) for locking. As a result, it may not be 161safe over NFS. This is where I choose security over either 162functionality or reliability. 163 164 165 RFC compliance. 166 167I tried to make popa3d as strictly RFC 1939 compliant as possible. 168Most other POP3 servers have extra "features" that violate the RFC. 169Examples include: wrapping long commands (no matter if they're valid 170or not) and thus generating multiple -ERR responses (if not even 171worse: processing something from the middle of the line as a command) 172to a single command, processing "LIST 4294967297" as "LIST 1" instead 173of reporting the error, ignoring past a NUL byte till end of line and 174thus misinterpreting the command. While these are mostly harmless, 175they can theoretically cause a POP3 client not to detect the 176unavailability of a protocol extension. 177 178There's however one place where popa3d's RFC compliance is 179deliberately relaxed: popa3d accepts commands terminated by single 180LFs, even though the RFC says the commands are terminated by a CRLF 181pair. 182 183 184 Performance. 185 186Despite the two extra "security" fork(2) calls, popa3d seems to behave 187fairly efficiently: the efficient mailbox parsing code and the lack of 188mailbox copying compensate for the extra fork's. 189 190Here's some real performance data that I've collected (popa3d running 191via inetd; larger sites would use the standalone mode instead): 192 193 24864 295.50re 16.92cp popa3d* 194 12749 4578.88re 15.50cp popa3d 195 196That is, 12749 POP3 sessions took 32.42 minutes of CPU time (on a 350 197MHz Pentium II); of those, more than a half was spent in the temporary 198child processes. It's not that bad though, as this system was running 199an (intentionally) expensive crypt(3) that got accounted to the child 200/etc/shadow authentication processes. 201 202Before upgrading to popa3d, the same machine was running qpopper (out 203of inetd, too): 204 205 12025 3169.38re 35.56cp popper 206 207It used to take a bit more CPU for less POP3 sessions. 208 209-- 210Solar Designer <solar at openwall.com> 211