diff options
| -rw-r--r-- | CHANGELOG.md | 2 | ||||
| -rw-r--r-- | FICS/addgroup.cpp | 21 | ||||
| -rw-r--r-- | FICS/addgroup.h | 1 | ||||
| -rw-r--r-- | FICS/fics_addplayer.c | 14 | ||||
| -rw-r--r-- | FICS/ficsmain.c | 7 | ||||
| -rw-r--r-- | FICS/playerdb.c | 40 | ||||
| -rw-r--r-- | FICS/prep_dir_for_privdrop.cpp | 6 |
7 files changed, 74 insertions, 17 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index ed3be06..ab3ddc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ documented in this file. `config.h` to `fics.conf` which is read at startup. - Added more open flags and changed the code to refer to them by using enums. +- Added overflow checks for array indices. Multiple occurrences. +- Added the possibility for the FICS to be installed system-wide. - Added usage of `unveil()` and `pledge()`. (OpenBSD mitigation techniques, so OpenBSD only.) - Assured that no conversion loss takes place when dealing with diff --git a/FICS/addgroup.cpp b/FICS/addgroup.cpp index 59547d0..52c6639 100644 --- a/FICS/addgroup.cpp +++ b/FICS/addgroup.cpp @@ -140,6 +140,27 @@ group_exists(const char *name) return false; } +bool +is_valid_group_name(const char *name) +{ + const char legal_index[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789_-"; + const size_t name_min = 2; + const size_t name_max = 30; + + if (name == nullptr || strcmp(name, "") == 0) + return false; + else if (strlen(name) < name_min || strlen(name) > name_max) + return false; + for (const char *cp = name; *cp != '\0'; cp++) { + if (strchr(legal_index, *cp) == nullptr) + return false; + } + return true; +} + int read_the_group_permissions_file(const char *path) { diff --git a/FICS/addgroup.h b/FICS/addgroup.h index e5b1906..3642969 100644 --- a/FICS/addgroup.h +++ b/FICS/addgroup.h @@ -11,6 +11,7 @@ int fics_addgroup(const char *); bool get_group_id(const char *, int *); bool get_next_line_from_file(FILE *, char **); // uses 'new[]' bool group_exists(const char *); +bool is_valid_group_name(const char *); int read_the_group_permissions_file(const char *); __FICS_END_DECLS diff --git a/FICS/fics_addplayer.c b/FICS/fics_addplayer.c index 18d42c4..b5ca47f 100644 --- a/FICS/fics_addplayer.c +++ b/FICS/fics_addplayer.c @@ -29,6 +29,9 @@ Markus Uhlin 24/05/25 Added command-line option 'a' Markus Uhlin 25/03/23 Output restart notice if the player is admin. + Markus Uhlin 25/11/02 Require root privileges if the + FICS prefix compares to anything + else than '/home'. */ #include "stdinclude.h" @@ -42,6 +45,7 @@ #include "fics_getsalt.h" #include "ficsmain.h" #include "playerdb.h" +#include "prep_dir_for_privdrop.h" #include "settings.h" #include "utils.h" @@ -136,6 +140,16 @@ main(int argc, char *argv[]) settings_init(); settings_read_conf(FICS_SETTINGS); + if (strncmp(FICS_PREFIX, "/home", 5) == 0) { + if (is_super_user()) + errx(1, "Do not run as root"); + } else { + if (!is_super_user()) + errx(1, "Need root privileges"); + else if (drop_root_privileges(FICS_PREFIX) == -1) + errx(1, "Privdrop failed"); + } + player_init(0); p = player_new(); diff --git a/FICS/ficsmain.c b/FICS/ficsmain.c index bf5aafb..36055b8 100644 --- a/FICS/ficsmain.c +++ b/FICS/ficsmain.c @@ -298,9 +298,12 @@ main(int argc, char *argv[]) settings_init(); settings_read_conf(FICS_SETTINGS); - if (is_super_user()) { - if (strncmp(FICS_PREFIX, "/home", 5) == 0) + if (strncmp(FICS_PREFIX, "/home", 5) == 0) { + if (is_super_user()) errx(1, "Do not run as root"); + } else { + if (!is_super_user()) + errx(1, "Need root privileges"); else if (read_the_group_permissions_file("/etc/group") != 0) errx(1, "Failed to read the group permissions file"); else if (fics_addgroup(settings_get("sysgroup")) != 0) diff --git a/FICS/playerdb.c b/FICS/playerdb.c index 2b8ef04..2fbc975 100644 --- a/FICS/playerdb.c +++ b/FICS/playerdb.c @@ -49,6 +49,8 @@ Markus Uhlin 25/07/28 Restricted file permissions upon creation. Markus Uhlin 25/07/30 Usage of 'int64_t'. + Markus Uhlin 25/11/02 Added overflow checks for array + indices. */ #include "stdinclude.h" @@ -1085,8 +1087,8 @@ player_read(int p, char *name) char line[MAX_LINE_SIZE] = { '\0' }; char *attr, *value; char *resolvedPath = NULL; - int len = 0; int version = 0; + size_t len = 0; parray[p].login = stolower(xstrdup(name)); // free on error? @@ -2072,17 +2074,25 @@ player_decline_offers(int p, int p1, int offerType) } while ((offer = player_find_pendfrom(p, p1, offerType)) >= 0) { + if (offer >= (int)ARRAY_SIZE(parray[0].p_from_list)) { + warnx("%s: 'offer' too large", __func__); + break; + } + type = parray[p].p_from_list[offer].type; p2 = parray[p].p_from_list[offer].whofrom; p2Name = parray[p2].name; - part = parray[p].partner; - if (part >= 0 && parray[part].partner != p) + if ((part = parray[p].partner) >= (int)ARRAY_SIZE(parray)) { + errx(1, "%s: 'part' (%d) too large", __func__, + part); + } else if (part >= 0 && parray[part].partner != p) part = -1; - p2part = parray[p2].partner; - - if (p2part >= 0 && parray[p2part].partner != p2) + if ((p2part = parray[p2].partner) >= (int)ARRAY_SIZE(parray)) { + errx(1, "%s: 'p2part' (%d) too large", __func__, + p2part); + } else if (p2part >= 0 && parray[p2part].partner != p2) p2part = -1; switch (type) { @@ -2185,17 +2195,25 @@ player_withdraw_offers(int p, int p1, int offerType) } while ((offer = player_find_pendto(p, p1, offerType)) >= 0) { + if (offer >= (int)ARRAY_SIZE(parray[0].p_to_list)) { + warnx("%s: 'offer' too large", __func__); + break; + } + type = parray[p].p_to_list[offer].type; p2 = parray[p].p_to_list[offer].whoto; p2Name = parray[p2].name; - part = parray[p].partner; - if (part >= 0 && parray[part].partner != p) + if ((part = parray[p].partner) >= (int)ARRAY_SIZE(parray)) { + errx(1, "%s: 'part' (%d) too large", __func__, + part); + } else if (part >= 0 && parray[part].partner != p) part = -1; - p2part = parray[p2].partner; - - if (p2part >= 0 && parray[p2part].partner != p2) + if ((p2part = parray[p2].partner) >= (int)ARRAY_SIZE(parray)) { + errx(1, "%s: 'p2part' (%d) too large", __func__, + p2part); + } else if (p2part >= 0 && parray[p2part].partner != p2) p2part = -1; switch (type) { diff --git a/FICS/prep_dir_for_privdrop.cpp b/FICS/prep_dir_for_privdrop.cpp index 85d3dfb..4d4478c 100644 --- a/FICS/prep_dir_for_privdrop.cpp +++ b/FICS/prep_dir_for_privdrop.cpp @@ -117,10 +117,8 @@ prep_dir_for_privdrop(const char *path) fs::recursive_directory_iterator dir_it(v_path); uid_t uid = 0; gid_t gid = 0; - constexpr mode_t dir_mode = (S_IRUSR|S_IWUSR| - S_IRGRP|S_IWGRP|S_IROTH); - constexpr mode_t file_mode = (S_IRUSR|S_IWUSR|S_IRGRP| - S_IROTH); + constexpr mode_t dir_mode = (S_IRWXU|S_IRGRP|S_IXGRP); + constexpr mode_t file_mode = (S_IRUSR|S_IWUSR|S_IRGRP); if (get_uid_and_gid(uid, gid) == -1) { throw std::runtime_error("failed to get uid/gid"); |
