BSD, C, httpd, SQLite

% vi main.c

You've deployed BCHS. Your editor is open. Where do you begin?

write portable and secure c

Anybody can write crappy, bug-ridden and insecure code. In any language. Good news: with C, it's even easier! So familiarise yourself with common (and common-sense) pitfalls noted in the SEI CERT C coding standard and comp.lang.c FAQ. When compiling, -W -Wall -Wextra -g -O0 should be standard: lots of warnings, symbols for if (when) your application crashes, and disabled optimisation to make the back traces readable.

To encourage sharing, consider style(9) as a guide for the style of your C code. It makes a significant difference when bringing on victims^Wfellow programmers!

Also consider portability: the more operating systems where your code works, the more folks you'll have using it. Consider using oconfigure or similar to easily add safe OpenBSD functions (strlcpy, strtonum, …) to any operating system.

There's a great deal more one can say here, but neither of us have time for a book. If you're on OpenBSD, it's trivial to safe-guard your C applications with pledge(2) and unveil(2). For portability, these can be conditional depending upon oconfigure. On other systems, you'll have a much harder time navigating the security mechanisms, so OpenBSD is a good place to start.

be familiar with cgi and fastcgi

If you don't want to parse content by hand—and you really, really don't—let a library do it for you. Install and use kcgi, kore, or basic fcgi from packages.

Even with a library handling your CGI and FastCGI parsing, you must still be knowledgeable of HTTP topics such as error codes (e.g., 301, 302, or 307 for redirects?), secure HTTP headers (e.g., those espoused by OWASP), and most mystically, browser caching.

Caveat emptor on FastCGI. Be careful! CGI scripts run by slowcgi(8) already have their privileges dropped and file-system constrained. With FastCGI, you'll need to use a framework that does so for you! There's certainly a speed boost in using FastCGI, but make sure it does not impair your application's security.

know your security tools

OpenBSD has pledge(2). Embrace the pledge. And even better: unveil(2). These functions are incredibly useful in creating a secure environment without elaborate frameworks in place.

Your application will be under assault every moment it's running. And it will have bugs: limit the damage caused by inevitable mistakes by constraining (sandboxing) the environment available to your application. Oh, right: there's also chroot(2), dropping privileges, etc…

For more on these security tools, see Secure CGI.

databases: simplicity rules

Spend time carefully reading through the SQLite documentation. For a simpler API (and some significant security features), consider using ksql or sqlbox. Most folks knee-jerk into needing the biggest Oracle or NoSQL database they can find. But for most applications, it's perfectly alright to start with SQLite and vanilla SQL, then slowly expand as necessary. The usual path is from SQLite to PostgreSQL.

If you don't fancy writing raw SQLite, there's always sqlitebrowser and kexi, both available as packages.


static source

Statically scan your binary with LLVM (from packages: the base system does not bundle with the scan-build utility). There's also frama-c and splint, both also in packages, but I haven't used either.

These static analysis tools can help catch source-level bugs. An alternative compiler (clang vs. gcc) can also prevent you from relying too much on compiler-specific extensions, which otherwise reduces portability.

If your project is open source, you can register it with Coverity, too.

Model checking is a technique currently espoused by security researchers, but I don't have any practical experience with model checking in C.


Run your application under valgrind (from packages) and make sure your malloc(3) system flags are unforgiving. The status of valgrind on OpenBSD is uncertain, so this is one reason I make sure a portable version of my software exists: running valgrind on other systems.

Memory errors are often the subtlest (next to race conditions, maybe). Use these tools as much as possible to catch any run-time issues that can't be ferreted with static analysis tools.

For your database, there's always tools like sqlmap to check your database connections. Of course, since you're using prepared parameters, this shouldn't be an issue. Right?


Parsing data? Push your parsers into libraries and use AFL (from packages) to put them through inputs you haven't tested.

The thought that this input could never happen is your adversary's favourite. It will happen. Make sure any parsing sequences are being run through as many code-paths as possible with this tool.


The strongest part of any BCHS toolchain is its documentation, particularly when using OpenBSD. In developing your application, be inspired to do the same: craft well-written manpages in mdoc. There's even a book: Practical UNIX Manpages. Regardless, mandoc(1) on your local BSD system will give you plentiful feedback on your syntax.

Given that your application involves more than just C (such as, for example, an exported REST API, you may also need to delve into the wild west of web development tools, such as Swagger or JSON Schema.

For your SQLite schemas, however, there's always sqliteconvert to browse the comments of your schema file.

Convinced? See it in action.

Don't forget: BSD is a community of professionals. Go to conferences (EuroBSDCon, AsiaBSDCon, BSDCan, etc.). Subscribe to the mailing lists. Donate. And lastly but most important of all: use the man pages!