% vi main.c
% vi main.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.
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
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
feature-test OpenBSD functions on other systems.
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.
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!
OpenBSD has pledge(2).
Embrace the pledge.
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.
Spend time carefully reading through the SQLite documentation. For a simpler API (and some significant security features), consider using ksql. 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 sqliteman, both available as packages.
Statically scan your binary with LLVM (from packages). There's also frama-c and splint, both also in packages.
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.
Run your application under valgrind (from packages) and make sure your malloc.conf(5) flags are unforgiving.
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 ksql and/or raw SQL 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
For your SQLite schemas, however, there's always sqliteconvert to browse the comments of your schema file.
Convinced? See it in action.