annotate doc/securecoding.txt @ 2810:74517c34a687 HEAD

Dovecot authentication protocol v1.0
author Timo Sirainen <tss@iki.fi>
date Fri, 22 Oct 2004 16:44:03 +0300
parents 6cb3cbf8c7c4
children b054cd10ceaa
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1787
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
1 Simplicity provides security. The more you have to remember to maintain
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
2 security the easier it is to forget something.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
3
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
4
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
5 Use Multiple Layers of Security
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
6 -------------------------------
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
7
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
8 Input validation is useful to prevent clients from taking too much server
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
9 resources. Add the restrictions only where it's useful. For example a
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
10 simple "maximum line length" will limit the length of pretty much all
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
11 possible client input.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
12
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
13 Don't rely on input validation. Maybe you missed something. Maybe someone
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
14 calls your function somewhere else where you didn't originally intend it.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
15 Maybe someone makes the input validation less restrictive for some reason.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
16 Point is, it's not an excuse to cause a security hole just because input
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
17 wasn't what you expected it to be.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
18
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
19 Don't trust memory. If code somewhere overflowed a buffer, don't make it
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
20 easier to exploit it. For example if you have code:
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
21
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
22 static char staticbuf[100];
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
23 ..
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
24 char stackbuf[100];
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
25 strcpy(stackbuf, staticbuf);
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
26
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
27 Just because staticbuf was declared as [100], it doesn't mean it couldn't
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
28 contain more data. Overflowing static buffers can't be directly exploited,
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
29 but the strcpy() overflowing stackbuf makes it possible. Always copy data
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
30 with bounds checking.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
31
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
32
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
33 Prevent Buffer Overflows
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
34 ------------------------
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
35
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
36 Avoid writing to buffers directly. Write everything through buffer API
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
37 (lib/buffer.h) which guarantees protection against buffer overflows.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
38 There are various safe string APIs as well (lib/str.h, lib/strfuncs.h).
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
39
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
40 If you do write to buffers directly, mark the code with /* @UNSAFE */
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
41 unless it's _obviously_ safe. Only obviously safe code is calling a
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
42 function with (buffer, sizeof(buffer)) parameters. If you do _any_
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
43 calculations with buffer size, mark it unsafe.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
44
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
45 Use const with buffers whenever you can. It guarantees that you can't
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
46 accidentally modify it.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
47
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
48 Use "char *" only for NUL-terminated strings. Use "unsigned char *"
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
49 if it's not guaranteed to be NUL-terminated.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
50
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
51
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
52 Avoid free()
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
53 ------------
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
54
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
55 Accessing freed memory is the most difficult problem to solve with C code.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
56 Only real solution is to use garbage collector, but it's not possible to
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
57 write a portable GC without radical changes in how you write code.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
58
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
59 I've added support for Boehm GC, but it doesn't seem to be working very
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
60 well currently. In any case I'd rather not make it required.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
61
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
62 There are a few ways to avoid most free() calls however: data stack and
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
63 memory pools.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
64
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
65 Data stack works in somewhat similiar way to C's control stack. alloca() is
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
66 quite near to what it does, but there's one major difference: Stack frames
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
67 are explicitly defined so functions can return values allocated from data
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
68 stack. t_strdup_printf() call is an excellent example of why this is useful.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
69 Rather than creating some arbitrary sized buffer and using snprintf() which
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
70 may truncate the value, you can just use t_strdup_printf() without worrying
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
71 about buffer sizes being large enough. See lib/data-stack.h
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
72
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
73 Memory pools are useful when you have to construct an object from multiple
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
74 pieces and you can free it all at once. Actually Dovecot's Memory Pool API
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
75 is just an abstract class for allocating memory. There's system_pool for
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
76 allocating memory with calloc(), realloc() and free() and you can create a
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
77 pool to allocate memory from data stack. If your function needs to allocate
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
78 memory for multiple objects, you may want to take struct pool as parameter
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
79 to allow caller to specify where the memory is allocated from.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
80 See lib/mempool.h
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
81
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
82
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
83 Don't Keep Secrets
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
84 ------------------
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
85
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
86 We don't do anything special to protect ourself against read access buffer
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
87 overflows, so don't store anything sensitive in memory. We use multiple
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
88 processes to protect sensitive information between users.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
89
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
90 When dealing with passwords and such, erase them from memory after you
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
91 don't need it anymore. Note that such memset() may be optimized away by
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
92 compiler, use safe_memset().
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
93
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
94
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
95 Use GCC Extensions
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
96 ------------------
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
97
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
98 GCC makes it easy to catch some potential errors:
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
99
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
100 Format string vulnerabilities can be prevented by marking all functions
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
101 using format strings with __attr_format__() and __attr_format_arg__()
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
102 macros and using -Wformat=2 GCC option.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
103
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
104 -W option checks that you don't compare signed and unsigned variables.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
105
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
106 I hope GCC will later emit a warning whenever there's potential integer
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
107 truncation. -Wconversion kind of does that, but it's not really meant for
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
108 it and it gives too many other useless warnings.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
109
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
110
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
111 Use union Safely
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
112 ----------------
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
113
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
114 Suppose there was code:
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
115
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
116 union {
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
117 unsigned int number;
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
118 char *str;
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
119 } u;
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
120
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
121 If it was possible for user to set number arbitrarily, but access the union
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
122 as string it'd be possible to read or write arbitrary memory locations.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
123
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
124 There's two ways to handle this. First would be to avoid union entirely and
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
125 use a struct instead. You don't really need the extra few bytes of memory
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
126 that union saves.
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
127
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
128 Another way is to access the union only through macro that verifies that
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
129 you're accessing it correctly. See IMAP_ARG_*() macros in
6cb3cbf8c7c4 Secure coding guide for Dovecot.
Timo Sirainen <tss@iki.fi>
parents:
diff changeset
130 lib-imap/imap-parser.h.