Acknowledgements
About the Author
Introduction
- qmail did not live in the lab
- Years of other systems
- What confidence means here
- How to read the case
- Returning to qmail
- What this book is
- qmail did not live in the lab
- Years of other systems
- What confidence means here
- How to read the case
- Returning to qmail
- What this book is
Chapter 1: The Mail Server Everyone Used
- Email was messy
- Sendmail adapted to a moving world
- Mail servers are dangerous programs
- The Internet learned this early
- Why qmail appeared
- Sendmail adapted, qmail distrusted
- The question
Chapter 2: Bug-of-the-Month Club
- Why MTAs were exposed
- Sendmail was part of that climate
- The fair version
- Operational fatigue
- Why the advisories matter
Chapter 3: Enter D. J. Bernstein
- The academic outside the vendor economy
- Code as public argument
- A larger software style
- Confidence and refusal
Chapter 4: A Mailing List, a Frustration, a New MTA
- The mailing list mattered
- What the workload revealed
- The early timeline moved fast
- Compatible at the edge, different inside
- Impatience with preventable failure
Chapter 5: The Design Bet
- Three ways to make software safer
- Eliminate bugs
- Eliminate code
- Eliminate trusted code
- The rules
- Patterns, not magic
Chapter 6: The First Release
- Why that matters
- Adoption
- Why people used it
- The frozen core
Chapter 7: No One Program Wears Every Hat
- Mail transfer is not one job
- Why this helps security
- Why this helps reliability
- Performance comes along for the ride
- The cost
Chapter 8: The Trust Map
- What the guarantee says
- The map
- Keep privilege narrow
- Distrust between components
- A bug is not enough
Chapter 9: Don’t Parse
- Why parsing is dangerous
- Sendmail had a reason to parse
- The concrete contrast
- Programs and files are not addresses
- Move the complexity
- The modern lesson
Chapter 10: The Queue as a Reliability Machine
- Accepted means accepted
- Queue insertion and queue management
- A message has a lifecycle
- The queue has shape
- Queue lifecycle diagram
- Performance is part of reliability
- Simple does not mean casual
Chapter 11: Maildir and the Filesystem
- One message, one file
- Maildir lifecycle diagram
- Why NFS mattered
- Unique names are part of the design
- The qmail pattern again
- Why it lasted
Chapter 12: Small Code, Fewer Bugs, Less Trusted Code
- Bernstein’s framework
- Smaller code
- Less trusted code
- Trusted code is a user question
- The question to ask
Chapter 13: The $500 Security Guarantee
- What the challenge did
- What counted
- The guarantee grew a history
- The legend simplified the claim
- Why the guarantee mattered
Chapter 14: What Does “No Security Hole” Mean?
- What qmail’s guarantee covered
- Boundaries are contested
- This is not only a qmail problem
- Scope is a design artifact
- A useful table
- The deployment proof
- The problem with the phrase
Chapter 15: Guninski, 64-Bit qmail, and the Uncomfortable Edge Case
- What changed
- Bernstein’s response
- Why 64-bit mattered
- The uncomfortable admission
- Time is part of the threat model
Chapter 16: Qualys Reopens the Case
- The main target
- From qmail-smtpd to qmail-local
- Documentation and defaults
- What changed between 2005 and 2020
- The practical lesson
Chapter 17: The Cost of Being Right in a Particular Way
- Licensing
- Patch culture
- Patches change the artifact
- The TLS example
- Correct ideas need a path to users
- The lesson
Chapter 18: Postfix, OpenSMTPD, and the Children of qmail
- Postfix
- OpenSMTPD
- A comparison
- The children are not clones
- What qmail did not decide
- No hero worship
Chapter 19: What Aged Well
- Privilege separation
- Small trusted cores
- Parsing skepticism
- Maildir
- The queue as a promise
- The public challenge
- What to keep
- The best question
Chapter 20: What Did Not
- The frozen upstream
- Patch culture
- Licensing
- C integer assumptions
- Documentation of assumptions
- Mechanisms that spent complexity badly
- Communication style
- The guarantee repeated badly
Chapter 21: The qmail Lesson
- The historical lesson
- The engineering lesson
- Confidence is structural
- The evidence should be visible
- Definitions matter
- Maintenance matters too
- What to take forward
- Confidence has to pass through reality
Appendix 1: Engineering Confidence Checklist
- 1. Define the claim
- 2. Draw the authority map
- 3. Find hostile input and parsers
- 4. Separate acceptance from completion
- 5. Make failure states inspectable
- 6. Name environmental assumptions
- 7. Define what would falsify the claim
- 8. Preserve the argument during change
- Short version
Appendix 2: The Bernstein Design Family
- Small programs with hard edges
- Separate roles other systems combine
- Privilege is something to shed
- Directories as control planes
- Durable success before saying yes
- User control without broad authority
- Refusal as a design tool
- Configuration should be generated, checked, or local
- The shared argument
Appendix 3: qmail and Zero Trust
- The perimeter moves inward
- The closest overlaps
- Components are not automatically friends
- Least privilege as structure
- Blast radius matters
- Hostile input is not only remote input
- Fixed policy instead of dynamic policy
- A useful mapping
- The lesson