diff options
Diffstat (limited to 'src/sysusers/sysusers.c')
-rw-r--r-- | src/sysusers/sysusers.c | 230 |
1 files changed, 78 insertions, 152 deletions
diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index d7ba482834..5d72493725 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -1,5 +1,3 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - /*** This file is part of systemd. @@ -19,26 +17,31 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <pwd.h> +#include <getopt.h> #include <grp.h> -#include <shadow.h> #include <gshadow.h> -#include <getopt.h> +#include <pwd.h> +#include <shadow.h> #include <utmp.h> -#include "util.h" -#include "hashmap.h" -#include "specifier.h" -#include "path-util.h" -#include "build.h" -#include "strv.h" +#include "alloc-util.h" #include "conf-files.h" #include "copy.h" -#include "utf8.h" +#include "def.h" +#include "fd-util.h" #include "fileio-label.h" -#include "uid-range.h" -#include "selinux-util.h" #include "formats-util.h" +#include "hashmap.h" +#include "path-util.h" +#include "selinux-util.h" +#include "smack-util.h" +#include "specifier.h" +#include "string-util.h" +#include "strv.h" +#include "uid-range.h" +#include "user-util.h" +#include "utf8.h" +#include "util.h" typedef enum ItemType { ADD_USER = 'u', @@ -67,7 +70,7 @@ typedef struct Item { static char *arg_root = NULL; -static const char conf_file_dirs[] = CONF_DIRS_NULSTR("sysusers"); +static const char conf_file_dirs[] = CONF_PATHS_NULSTR("sysusers.d"); static Hashmap *users = NULL, *groups = NULL; static Hashmap *todo_uids = NULL, *todo_gids = NULL; @@ -207,7 +210,7 @@ static int make_backup(const char *target, const char *x) { if (r < 0) return r; - r = copy_bytes(src, fileno(dst), (off_t) -1, true); + r = copy_bytes(src, fileno(dst), (uint64_t) -1, true); if (r < 0) goto fail; @@ -275,7 +278,7 @@ static int putgrent_with_members(const struct group *gr, FILE *group) { errno = 0; if (putgrent(&t, group) != 0) - return errno ? -errno : -EIO; + return errno > 0 ? -errno : -EIO; return 1; } @@ -283,7 +286,7 @@ static int putgrent_with_members(const struct group *gr, FILE *group) { errno = 0; if (putgrent(gr, group) != 0) - return errno ? -errno : -EIO; + return errno > 0 ? -errno : -EIO; return 0; } @@ -325,7 +328,7 @@ static int putsgent_with_members(const struct sgrp *sg, FILE *gshadow) { errno = 0; if (putsgent(&t, gshadow) != 0) - return errno ? -errno : -EIO; + return errno > 0 ? -errno : -EIO; return 1; } @@ -333,7 +336,7 @@ static int putsgent_with_members(const struct sgrp *sg, FILE *gshadow) { errno = 0; if (putsgent(sg, gshadow) != 0) - return errno ? -errno : -EIO; + return errno > 0 ? -errno : -EIO; return 0; } @@ -353,6 +356,19 @@ static int sync_rights(FILE *from, FILE *to) { return 0; } +static int rename_and_apply_smack(const char *temp_path, const char *dest_path) { + int r = 0; + if (rename(temp_path, dest_path) < 0) + return -errno; + +#ifdef SMACK_RUN_LABEL + r = mac_smack_apply(dest_path, SMACK_ATTR_ACCESS, SMACK_FLOOR_LABEL); + if (r < 0) + return r; +#endif + return r; +} + static int write_files(void) { _cleanup_fclose_ FILE *passwd = NULL, *group = NULL, *shadow = NULL, *gshadow = NULL; @@ -392,11 +408,13 @@ static int write_files(void) { i = hashmap_get(groups, gr->gr_name); if (i && i->todo_group) { + log_error("%s: Group \"%s\" already exists.", group_path, gr->gr_name); r = -EEXIST; goto finish; } if (hashmap_contains(todo_gids, GID_TO_PTR(gr->gr_gid))) { + log_error("%s: Detected collision for GID " GID_FMT ".", group_path, gr->gr_gid); r = -EEXIST; goto finish; } @@ -464,6 +482,7 @@ static int write_files(void) { i = hashmap_get(groups, sg->sg_namp); if (i && i->todo_group) { + log_error("%s: Group \"%s\" already exists.", gshadow_path, sg->sg_namp); r = -EEXIST; goto finish; } @@ -530,11 +549,13 @@ static int write_files(void) { i = hashmap_get(users, pw->pw_name); if (i && i->todo_user) { + log_error("%s: User \"%s\" already exists.", passwd_path, pw->pw_name); r = -EEXIST; goto finish; } if (hashmap_contains(todo_uids, UID_TO_PTR(pw->pw_uid))) { + log_error("%s: Detected collision for UID " UID_FMT ".", passwd_path, pw->pw_uid); r = -EEXIST; goto finish; } @@ -699,42 +720,34 @@ static int write_files(void) { /* And make the new files count */ if (group_changed) { if (group) { - if (rename(group_tmp, group_path) < 0) { - r = -errno; + r = rename_and_apply_smack(group_tmp, group_path); + if (r < 0) goto finish; - } - free(group_tmp); - group_tmp = NULL; + group_tmp = mfree(group_tmp); } if (gshadow) { - if (rename(gshadow_tmp, gshadow_path) < 0) { - r = -errno; + r = rename_and_apply_smack(gshadow_tmp, gshadow_path); + if (r < 0) goto finish; - } - free(gshadow_tmp); - gshadow_tmp = NULL; + gshadow_tmp = mfree(gshadow_tmp); } } if (passwd) { - if (rename(passwd_tmp, passwd_path) < 0) { - r = -errno; + r = rename_and_apply_smack(passwd_tmp, passwd_path); + if (r < 0) goto finish; - } - free(passwd_tmp); - passwd_tmp = NULL; + passwd_tmp = mfree(passwd_tmp); } if (shadow) { - if (rename(shadow_tmp, shadow_path) < 0) { - r = -errno; + r = rename_and_apply_smack(shadow_tmp, shadow_path); + if (r < 0) goto finish; - } - free(shadow_tmp); - shadow_tmp = NULL; + shadow_tmp = mfree(shadow_tmp); } r = 0; @@ -891,8 +904,10 @@ static int add_user(Item *i) { i->uid = p->pw_uid; i->uid_set = true; - free(i->description); - i->description = strdup(p->pw_gecos); + r = free_and_strdup(&i->description, p->pw_gecos); + if (r < 0) + return log_oom(); + return 0; } if (!IN_SET(errno, 0, ENOENT)) @@ -931,7 +946,7 @@ static int add_user(Item *i) { } } - /* Otherwise try to reuse the group ID */ + /* Otherwise, try to reuse the group ID */ if (!i->uid_set && i->gid_set) { r = uid_is_ok((uid_t) i->gid, i->name); if (r < 0) @@ -1149,9 +1164,8 @@ static int process_item(Item *i) { } if (i->gid_path) { - free(j->gid_path); - j->gid_path = strdup(i->gid_path); - if (!j->gid_path) + r = free_and_strdup(&j->gid_path, i->gid_path); + if (r < 0) return log_oom(); } @@ -1285,81 +1299,6 @@ static bool item_equal(Item *a, Item *b) { return true; } -static bool valid_user_group_name(const char *u) { - const char *i; - long sz; - - if (isempty(u)) - return false; - - if (!(u[0] >= 'a' && u[0] <= 'z') && - !(u[0] >= 'A' && u[0] <= 'Z') && - u[0] != '_') - return false; - - for (i = u+1; *i; i++) { - if (!(*i >= 'a' && *i <= 'z') && - !(*i >= 'A' && *i <= 'Z') && - !(*i >= '0' && *i <= '9') && - *i != '_' && - *i != '-') - return false; - } - - sz = sysconf(_SC_LOGIN_NAME_MAX); - assert_se(sz > 0); - - if ((size_t) (i-u) > (size_t) sz) - return false; - - if ((size_t) (i-u) > UT_NAMESIZE - 1) - return false; - - return true; -} - -static bool valid_gecos(const char *d) { - - if (!d) - return false; - - if (!utf8_is_valid(d)) - return false; - - if (string_has_cc(d, NULL)) - return false; - - /* Colons are used as field separators, and hence not OK */ - if (strchr(d, ':')) - return false; - - return true; -} - -static bool valid_home(const char *p) { - - if (isempty(p)) - return false; - - if (!utf8_is_valid(p)) - return false; - - if (string_has_cc(p, NULL)) - return false; - - if (!path_is_absolute(p)) - return false; - - if (!path_is_safe(p)) - return false; - - /* Colons are used as field separators, and hence not OK */ - if (strchr(p, ':')) - return false; - - return true; -} - static int parse_line(const char *fname, unsigned line, const char *buffer) { static const Specifier specifier_table[] = { @@ -1383,7 +1322,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { /* Parse columns */ p = buffer; - r = unquote_many_words(&p, 0, &action, &name, &id, &description, &home, NULL); + r = extract_many_words(&p, NULL, EXTRACT_QUOTES, &action, &name, &id, &description, &home, NULL); if (r < 0) { log_error("[%s:%u] Syntax error.", fname, line); return r; @@ -1392,7 +1331,7 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { log_error("[%s:%u] Missing action and name columns.", fname, line); return -EINVAL; } - if (*p != 0) { + if (!isempty(p)) { log_error("[%s:%u] Trailing garbage.", fname, line); return -EINVAL; } @@ -1404,15 +1343,13 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { } if (!IN_SET(action[0], ADD_USER, ADD_GROUP, ADD_MEMBER, ADD_RANGE)) { - log_error("[%s:%u] Unknown command command type '%c'.", fname, line, action[0]); + log_error("[%s:%u] Unknown command type '%c'.", fname, line, action[0]); return -EBADMSG; } /* Verify name */ - if (isempty(name) || streq(name, "-")) { - free(name); - name = NULL; - } + if (isempty(name) || streq(name, "-")) + name = mfree(name); if (name) { r = specifier_printf(name, specifier_table, NULL, &resolved_name); @@ -1428,10 +1365,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { } /* Verify id */ - if (isempty(id) || streq(id, "-")) { - free(id); - id = NULL; - } + if (isempty(id) || streq(id, "-")) + id = mfree(id); if (id) { r = specifier_printf(id, specifier_table, NULL, &resolved_id); @@ -1442,10 +1377,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { } /* Verify description */ - if (isempty(description) || streq(description, "-")) { - free(description); - description = NULL; - } + if (isempty(description) || streq(description, "-")) + description = mfree(description); if (description) { if (!valid_gecos(description)) { @@ -1455,10 +1388,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) { } /* Verify home */ - if (isempty(home) || streq(home, "-")) { - free(home); - home = NULL; - } + if (isempty(home) || streq(home, "-")) + home = mfree(home); if (home) { if (!valid_home(home)) { @@ -1764,7 +1695,7 @@ static int parse_argv(int argc, char *argv[]) { {} }; - int c; + int c, r; assert(argc >= 0); assert(argv); @@ -1778,17 +1709,12 @@ static int parse_argv(int argc, char *argv[]) { return 0; case ARG_VERSION: - puts(PACKAGE_STRING); - puts(SYSTEMD_FEATURES); - return 0; + return version(); case ARG_ROOT: - free(arg_root); - arg_root = path_make_absolute_cwd(optarg); - if (!arg_root) - return log_oom(); - - path_kill_slashes(arg_root); + r = parse_path_argument_and_warn(optarg, true, &arg_root); + if (r < 0) + return r; break; case '?': @@ -1819,7 +1745,7 @@ int main(int argc, char *argv[]) { umask(0022); - r = mac_selinux_init(NULL); + r = mac_selinux_init(); if (r < 0) { log_error_errno(r, "SELinux setup failed: %m"); goto finish; @@ -1863,7 +1789,7 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; - lock = take_password_lock(arg_root); + lock = take_etc_passwd_lock(arg_root); if (lock < 0) { log_error_errno(lock, "Failed to take lock: %m"); goto finish; |