Code refactoring: get_file_mime got into mime.c and all security code moved into a procedure

This commit is contained in:
Solene Rapenne 2020-12-04 19:08:36 +01:00
parent e03ed1ca2b
commit 345215fa9b
2 changed files with 79 additions and 63 deletions

117
main.c
View file

@ -21,10 +21,62 @@
void display_file(const char *, const char *); void display_file(const char *, const char *);
void status (const int, const char *, const char *); void status (const int, const char *, const char *);
void get_file_mime(const char *, char *, const ssize_t); void get_file_mime(const char *, char *, const ssize_t);
void drop_privileges(const char *, const char *);
int main (int, char **); int main (int, char **);
void
drop_privileges(const char *user, const char *path)
{
struct passwd *pw;
/*
* use chroot() if an user is specified requires root user to be
* running the program to run chroot() and then drop privileges
*/
if (strlen(user) > 0) {
/* is root? */
if (getuid() != 0) {
syslog(LOG_DAEMON, "chroot requires program to be run as root");
err(1, "chroot requires root user");
}
/* search user uid from name */
if ((pw = getpwnam(user)) == NULL) {
syslog(LOG_DAEMON, "the user %s can't be found on the system", user);
err(1, "finding user");
}
/* chroot worked? */
if (chroot(path) != 0) {
syslog(LOG_DAEMON, "the path %s can't be used for chroot", path);
err(1, "chroot");
}
/* drop privileges */
if (setuid(pw->pw_uid) != 0) {
syslog(LOG_DAEMON, "dropping privileges to user %s (uid=%i) failed",
user, pw->pw_uid);
err(1, "Can't drop privileges");
}
}
#ifdef __OpenBSD__
/*
* prevent access to files other than the one in path
*/
if (unveil(path, "r") == -1) {
syslog(LOG_DAEMON, "unveil on %s failed", path);
err(1, "unveil");
}
/*
* prevent system calls other parsing queryfor fread file and
* write to stdio
*/
if (pledge("stdio rpath", NULL) == -1) {
syslog(LOG_DAEMON, "pledge call failed");
err(1, "pledge");
}
#endif
}
void void
status(const int code, const char *file_mime, const char *lang) status(const int code, const char *file_mime, const char *lang)
{ {
@ -32,26 +84,6 @@ status(const int code, const char *file_mime, const char *lang)
code, file_mime, lang); code, file_mime, lang);
} }
void
get_file_mime(const char *path, char *type, const ssize_t type_size)
{
char *extension;
extension = strrchr(path, '.');
/* look for the MIME in the database */
for (int i = 0; i < sizeof(database) / sizeof(struct mimes); i++) {
if (strcmp(database[i].extension, extension + 1) == 0) {
strlcpy(type, database[i].type, type_size);
break;
}
}
/* if no MIME have been found, set a default one */
if (strlen(type) == 0)
strlcpy(type, "text/gemini", type_size);
}
void void
display_file(const char *path, const char *lang) display_file(const char *path, const char *lang)
{ {
@ -102,7 +134,6 @@ main(int argc, char **argv)
int virtualhost = 0; int virtualhost = 0;
int option; int option;
int start_with_gemini; int start_with_gemini;
struct passwd *pw;
char *pos; char *pos;
while ((option = getopt(argc, argv, ":d:l:u:v")) != -1) { while ((option = getopt(argc, argv, ":d:l:u:v")) != -1) {
@ -123,49 +154,9 @@ main(int argc, char **argv)
} }
/* /*
* use chroot() if an user is specified requires root user to be * do chroot if an user is supplied run pledge/unveil if OpenBSD
* running the program to run chroot() and then drop privileges
*/ */
if (strlen(user) > 0) { drop_privileges(user, path);
/* is root? */
if (getuid() != 0) {
syslog(LOG_DAEMON, "chroot requires %s to be run as root", argv[0]);
err(1, "chroot requires root user");
}
/* search user uid from name */
if ((pw = getpwnam(user)) == NULL) {
syslog(LOG_DAEMON, "the user %s can't be found on the system", user);
err(1, "finding user");
}
/* chroot worked? */
if (chroot(path) != 0) {
syslog(LOG_DAEMON, "the path %s can't be used for chroot", path);
err(1, "chroot");
}
/* drop privileges */
if (setuid(pw->pw_uid) != 0) {
syslog(LOG_DAEMON, "dropping privileges to user %s (uid=%i) failed",
user, pw->pw_uid);
err(1, "Can't drop privileges");
}
}
#ifdef __OpenBSD__
/*
* prevent access to files other than the one in path
*/
if (unveil(path, "r") == -1) {
syslog(LOG_DAEMON, "unveil on %s failed", path);
err(1, "unveil");
}
/*
* prevent system calls other parsing queryfor fread file and
* write to stdio
*/
if (pledge("stdio rpath", NULL) == -1) {
syslog(LOG_DAEMON, "pledge call failed");
err(1, "pledge");
}
#endif
/* /*
* read 1024 chars from stdin * read 1024 chars from stdin

25
mimes.c
View file

@ -1,10 +1,15 @@
#include <string.h> #include <string.h>
#include <unistd.h>
#include <string.h>
void get_file_mime(const char *, char *, const ssize_t);
struct mimes { struct mimes {
char extension[10]; char extension[10];
char type [70]; char type [70];
}; };
struct mimes database[] = { struct mimes database[] = {
{"7z", "application/x-7z-compressed"}, {"7z", "application/x-7z-compressed"},
{"atom", "application/atom+xml"}, {"atom", "application/atom+xml"},
@ -110,3 +115,23 @@ struct mimes database[] = {
{"xpi", "application/x-xpinstall"}, {"xpi", "application/x-xpinstall"},
{"zip", "application/zip"} {"zip", "application/zip"}
}; };
void
get_file_mime(const char *path, char *type, const ssize_t type_size)
{
char *extension;
extension = strrchr(path, '.');
/* look for the MIME in the database */
for (int i = 0; i < sizeof(database) / sizeof(struct mimes); i++) {
if (strcmp(database[i].extension, extension + 1) == 0) {
strlcpy(type, database[i].type, type_size);
break;
}
}
/* if no MIME have been found, set a default one */
if (strlen(type) == 0)
strlcpy(type, "text/gemini", type_size);
}