]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/sysusers/sysusers.c
Merge pull request #2080 from chaloulo/split-mode-host-remove-port-from-journal-filename
[thirdparty/systemd.git] / src / sysusers / sysusers.c
index b3fa29b84cd578bcb5f528782fad8b34b06cde7a..90a2111ec59184bffd21e10b517db6aaa1fb5d4e 100644 (file)
   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 +72,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 +212,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 +280,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 +288,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 +330,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 +338,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 +358,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 +410,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 %d.", group_path, gr->gr_gid);
                                         r = -EEXIST;
                                         goto finish;
                                 }
@@ -464,6 +484,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 +551,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 %d.", passwd_path, pw->pw_uid);
                                         r = -EEXIST;
                                         goto finish;
                                 }
@@ -699,42 +722,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;
@@ -933,7 +948,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)
@@ -1384,7 +1399,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;
@@ -1393,7 +1408,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;
         }
@@ -1410,10 +1425,8 @@ static int parse_line(const char *fname, unsigned line, const char *buffer) {
         }
 
         /* 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);
@@ -1429,10 +1442,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);
@@ -1443,10 +1454,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)) {
@@ -1456,10 +1465,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)) {
@@ -1765,7 +1772,7 @@ static int parse_argv(int argc, char *argv[]) {
                 {}
         };
 
-        int c;
+        int c, r;
 
         assert(argc >= 0);
         assert(argv);
@@ -1779,17 +1786,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 '?':
@@ -1864,7 +1866,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;