...
The following non-compliant code example creates a file with some hard coded file_name
filename
(presumably in a shared directory such as /tmp
or C:\Temp
).
Code Block |
---|
|
char file_namefilename[] = /* hard coded string */;
FILE *fp = fopen(file_namefilename, "wb+");
if (fp == NULL) {
/* Handle Error */
}
|
...
Code Block |
---|
|
char file_namefilename[L_tmpnam];
FILE* fp;
if (!tmpnam(file_namefilename)) {
/* Handle Error */
}
/* A TOCTOU race condition exists here */
fp = fopen(file_namefilename, "wb+");
if (fp == NULL) {
/* Handle Error */
}
|
...
Wiki Markup |
---|
This next non-compliant code example attempts to remedy the problem by using the POSIX {{open()}} function, and providing a mechanism to indicate whether an existing file has been opened for writing or a new file has been created \[[Open Group 04|AA. C References#Open Group 04]\]. If the {{O_CREAT}} and {{O_EXCL}} flags are used together, the {{open()}} function fails when the file specified by {{file_namefilename}} already exists. To prevent an existing file from being opened and truncated, include the flags {{O_CREAT}} and {{O_EXCL}} when calling {{open()}}. |
Code Block |
---|
|
char file_namefilename[L_tmpnam];
int fd;
if (!(tmpnam(file_namefilename))) {
/* Handle Error */
}
/* A TOCTOU race condition exists here */
fd = open(file_namefilename, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0600);
if (fd < 0) {
/* Handle Error */
}
|
This call to open()
fails whenever file_name
filename
already exists, including when it is a symbolic link. This is secure, but a temporary file is presumably still required. Unfortunately, the method used by tmpnam()
to generate file names is not guaranteed to be unpredictable, which leaves room for an attacker to guess the file name ahead of time.
...
Code Block |
---|
|
char file_namefilename[L_tmpnam_s];
int fd;
if (tmpnam_s(file_namefilename, L_tmpnam_s) != 0) {
/* Handle Error */
}
/* A TOCTOU race condition exists here */
fd = open(file_namefilename, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0600);
if (fd < 0) {
/* Handle Error */
}
|
...
Code Block |
---|
|
char file_namefilename[] = "tmp-XXXXXX";
int fd;
if (!mktemp(file_namefilename)) {
/* Handle Error */
}
/* A TOCTOU race condition exists here */
fd = open(file_namefilename, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0600);
if (fd < 0) {
/* Handle Error */
}
|
...