diff options
Diffstat (limited to 'src/utils.c')
-rw-r--r-- | src/utils.c | 302 |
1 files changed, 145 insertions, 157 deletions
diff --git a/src/utils.c b/src/utils.c index fc65af0..679d027 100644 --- a/src/utils.c +++ b/src/utils.c @@ -37,181 +37,169 @@ int send_http_message (struct conn_s *connptr, int http_code, const char *error_title, const char *message) { - static const char *headers[] = { - "Server: " PACKAGE "/" VERSION, - "Content-type: text/html", - "Connection: close" - }; + static const char *headers[] = { + "Server: " PACKAGE "/" VERSION, + "Content-type: text/html", + "Connection: close" + }; - http_message_t msg; + http_message_t msg; - msg = http_message_create (http_code, error_title); - if (msg == NULL) - return -1; + msg = http_message_create (http_code, error_title); + if (msg == NULL) + return -1; - http_message_add_headers (msg, headers, 3); - http_message_set_body (msg, message, strlen (message)); - http_message_send (msg, connptr->client_fd); - http_message_destroy (msg); + http_message_add_headers (msg, headers, 3); + http_message_set_body (msg, message, strlen (message)); + http_message_send (msg, connptr->client_fd); + http_message_destroy (msg); - return 0; + return 0; } /* * Safely creates filename and returns the low-level file descriptor. */ -int -create_file_safely (const char *filename, unsigned int truncate_file) +int create_file_safely (const char *filename, unsigned int truncate_file) { - struct stat lstatinfo; - int fildes; - - /* - * lstat() the file. If it doesn't exist, create it with O_EXCL. - * If it does exist, open it for writing and perform the fstat() - * check. - */ - if (lstat (filename, &lstatinfo) < 0) - { - /* - * If lstat() failed for any reason other than "file not - * existing", exit. - */ - if (errno != ENOENT) - { - fprintf (stderr, - "%s: Error checking file %s: %s\n", - PACKAGE, filename, strerror (errno)); - return -EACCES; - } - - /* - * The file doesn't exist, so create it with O_EXCL to make - * sure an attacker can't slip in a file between the lstat() - * and open() - */ - if ((fildes = open (filename, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) - { - fprintf (stderr, - "%s: Could not create file %s: %s\n", - PACKAGE, filename, strerror (errno)); - return fildes; - } - } - else - { - struct stat fstatinfo; - int flags; - - flags = O_RDWR; - if (!truncate_file) - flags |= O_APPEND; - - /* - * Open an existing file. - */ - if ((fildes = open (filename, flags)) < 0) - { - fprintf (stderr, - "%s: Could not open file %s: %s\n", - PACKAGE, filename, strerror (errno)); - return fildes; - } - - /* - * fstat() the opened file and check that the file mode bits, - * inode, and device match. - */ - if (fstat (fildes, &fstatinfo) < 0 - || lstatinfo.st_mode != fstatinfo.st_mode - || lstatinfo.st_ino != fstatinfo.st_ino - || lstatinfo.st_dev != fstatinfo.st_dev) - { - fprintf (stderr, - "%s: The file %s has been changed before it could be opened\n", - PACKAGE, filename); - close (fildes); - return -EIO; - } - - /* - * If the above check was passed, we know that the lstat() - * and fstat() were done on the same file. Now we check that - * there's only one link, and that it's a normal file (this - * isn't strictly necessary because the fstat() vs lstat() - * st_mode check would also find this) - */ - if (fstatinfo.st_nlink > 1 || !S_ISREG (lstatinfo.st_mode)) - { - fprintf (stderr, - "%s: The file %s has too many links, " - "or is not a regular file: %s\n", - PACKAGE, filename, strerror (errno)); - close (fildes); - return -EMLINK; - } - - /* - * Just return the file descriptor if we _don't_ want the file - * truncated. - */ - if (!truncate_file) - return fildes; - - /* - * On systems which don't support ftruncate() the best we can - * do is to close the file and reopen it in create mode, which - * unfortunately leads to a race condition, however "systems - * which don't support ftruncate()" is pretty much SCO only, - * and if you're using that you deserve what you get. - * ("Little sympathy has been extended") - */ + struct stat lstatinfo; + int fildes; + + /* + * lstat() the file. If it doesn't exist, create it with O_EXCL. + * If it does exist, open it for writing and perform the fstat() + * check. + */ + if (lstat (filename, &lstatinfo) < 0) { + /* + * If lstat() failed for any reason other than "file not + * existing", exit. + */ + if (errno != ENOENT) { + fprintf (stderr, + "%s: Error checking file %s: %s\n", + PACKAGE, filename, strerror (errno)); + return -EACCES; + } + + /* + * The file doesn't exist, so create it with O_EXCL to make + * sure an attacker can't slip in a file between the lstat() + * and open() + */ + if ((fildes = + open (filename, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0) { + fprintf (stderr, "%s: Could not create file %s: %s\n", + PACKAGE, filename, strerror (errno)); + return fildes; + } + } else { + struct stat fstatinfo; + int flags; + + flags = O_RDWR; + if (!truncate_file) + flags |= O_APPEND; + + /* + * Open an existing file. + */ + if ((fildes = open (filename, flags)) < 0) { + fprintf (stderr, + "%s: Could not open file %s: %s\n", + PACKAGE, filename, strerror (errno)); + return fildes; + } + + /* + * fstat() the opened file and check that the file mode bits, + * inode, and device match. + */ + if (fstat (fildes, &fstatinfo) < 0 + || lstatinfo.st_mode != fstatinfo.st_mode + || lstatinfo.st_ino != fstatinfo.st_ino + || lstatinfo.st_dev != fstatinfo.st_dev) { + fprintf (stderr, + "%s: The file %s has been changed before it could be opened\n", + PACKAGE, filename); + close (fildes); + return -EIO; + } + + /* + * If the above check was passed, we know that the lstat() + * and fstat() were done on the same file. Now we check that + * there's only one link, and that it's a normal file (this + * isn't strictly necessary because the fstat() vs lstat() + * st_mode check would also find this) + */ + if (fstatinfo.st_nlink > 1 || !S_ISREG (lstatinfo.st_mode)) { + fprintf (stderr, + "%s: The file %s has too many links, " + "or is not a regular file: %s\n", + PACKAGE, filename, strerror (errno)); + close (fildes); + return -EMLINK; + } + + /* + * Just return the file descriptor if we _don't_ want the file + * truncated. + */ + if (!truncate_file) + return fildes; + + /* + * On systems which don't support ftruncate() the best we can + * do is to close the file and reopen it in create mode, which + * unfortunately leads to a race condition, however "systems + * which don't support ftruncate()" is pretty much SCO only, + * and if you're using that you deserve what you get. + * ("Little sympathy has been extended") + */ #ifdef HAVE_FTRUNCATE - ftruncate (fildes, 0); + ftruncate (fildes, 0); #else - close (fildes); - if ((fildes = open (filename, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) - { - fprintf (stderr, - "%s: Could not open file %s: %s.", - PACKAGE, filename, strerror (errno)); - return fildes; - } + close (fildes); + if ((fildes = + open (filename, O_RDWR | O_CREAT | O_TRUNC, 0600)) < 0) { + fprintf (stderr, "%s: Could not open file %s: %s.", + PACKAGE, filename, strerror (errno)); + return fildes; + } #endif /* HAVE_FTRUNCATE */ - } + } - return fildes; + return fildes; } /* * Write the PID of the program to the specified file. */ -int -pidfile_create (const char *filename) +int pidfile_create (const char *filename) { - int fildes; - FILE *fd; - - /* - * Create a new file - */ - if ((fildes = create_file_safely (filename, TRUE)) < 0) - return fildes; - - /* - * Open a stdio file over the low-level one. - */ - if ((fd = fdopen (fildes, "w")) == NULL) - { - fprintf (stderr, - "%s: Could not write PID file %s: %s.", - PACKAGE, filename, strerror (errno)); - close (fildes); - unlink (filename); - return -EIO; - } - - fprintf (fd, "%ld\n", (long) getpid ()); - fclose (fd); - return 0; + int fildes; + FILE *fd; + + /* + * Create a new file + */ + if ((fildes = create_file_safely (filename, TRUE)) < 0) + return fildes; + + /* + * Open a stdio file over the low-level one. + */ + if ((fd = fdopen (fildes, "w")) == NULL) { + fprintf (stderr, + "%s: Could not write PID file %s: %s.", + PACKAGE, filename, strerror (errno)); + close (fildes); + unlink (filename); + return -EIO; + } + + fprintf (fd, "%ld\n", (long) getpid ()); + fclose (fd); + return 0; } |