Security

This page examines the techniques used in maild to maximise system security.

The law of least privilege

OpenMTA follows the law of least privilege. maild runs in a chroot(2) environment at /var/mail. It runs under a unique, non-privileged UID and GID. It does not communicate with other processes on the local system.

Common security flaws in C programs

In writing maild, I tried to avoid the following problems:

String handling

The use of fixed width buffers for storing strings is inherantly dangerous. To mitigate the risk, a string library has been developed with the following functions:

/* String library */

#define strpnew(s) do { memset(s + sizeof(s) - 1, 0, 1); memset(s, 0, 1); } while (0)
#define strpcpy(a,b) strncpy((char *) a, (char *) b, sizeof(a))
#define strpcat(a,b) strncat((char *) a, (char *) b, sizeof(a) - 1)
#define strprintf(a,b,...) snprintf(a, sizeof(a) - 1, b, __VA_ARGS__)

#endif

These functions operate on automatic (stack-based) strings and can use the sizeof() operator to pass the length of the string through to the underlying C library function. Strings are never allocated on the heap.

Memory management

Automatic, or locally scoped, variables are used wherever possible.

Format strings

Format strings never use user supplied formats. See below:


/* Good */
printf("%s", some_user_data);

/* Bad */
printf(some_user_data);

Return values and exception handling

As a general rule, functions return an integer value of zero to indicate success and return negative one to indicate failure.

Calling functions are expected to check this value and propagate errors upward through the call stack. This produces a complete backtrace of the error in the logfile.

Two macros are defined for exception handling: throw() and catch(). When a function detects an error, it calls throw() and provides a description of the error.

Here is an example that shows a simple and an advanced usage of these macros:

#define throw(s) log_error(s); goto error;
#define catch()    return 0; \
                error: \
                   return -1;

int simple_function()
{
	int fd;

	if (advanced_function() < 0)
	    throw("advanced function failed");

	catch();
}

int advanced_function()
{
	int fd = -1;
	int retval = 0;

	if (creat(fd, "some.file") < 0)
	    throw("Unable to create some.file");

	if (fork() < 0)
	    throw("Unable to fork()");

	/* ... */

	goto cleanup;
	
error:
	retval = -1;

cleanup:
	if (fd >= 0)
	      close(fd);

	return retval;	
}

Peer review

Security professionals, and qualified members of the general public, are invited to review the source code to find security flaws. The current codebase contains approximately 1500 lines of heavily commented code. If you participate, your assessment will be posted on the maild website, unedited in it's entirety.

Since maild is a BSD-licensed free software program, there is no financial compensation for participating in the code review process. However, by helping maild become a "secure" program, your name and analysis will be made public so that future employers or clients can judge your work.

Please send an email message containing a summary of your code review to devel@heily.com, and make sure to include the following information:

Your complete email message -- including message headers -- will be posted, unedited, on this page.

Thanks in advance for your help,

-Mark Heily


$Id: security.html,v 1.1.1.1 2006/03/19 00:23:14 mheily Exp $