diff --git a/Makefile-rpm-ostree.am b/Makefile-rpm-ostree.am index 2f3108aa39..ee3ed87f54 100644 --- a/Makefile-rpm-ostree.am +++ b/Makefile-rpm-ostree.am @@ -58,7 +58,8 @@ rpm_ostree_SOURCES = src/app/main.c \ src/app/rpmostree-polkit-agent.c \ src/app/rpmostree-polkit-agent.h \ src/app/rpmostree-builtin-kargs.c \ - $(NULL) + src/app/rpmostree-builtin-temp-convert.c \ + $(NULL) if BUILDOPT_COMPOSE_TOOLING rpm_ostree_SOURCES += \ diff --git a/src/app/main.c b/src/app/main.c index 04685ce6a4..2fd6012d4a 100644 --- a/src/app/main.c +++ b/src/app/main.c @@ -95,6 +95,9 @@ static RpmOstreeCommand commands[] = { { "kargs", 0, "Query or modify kernel arguments", rpmostree_builtin_kargs }, + { "temp-convert", RPM_OSTREE_BUILTIN_FLAG_LOCAL_CMD, + "temp command to convert passwd/group conversion", + rpmostree_builtin_temp_convert }, /* Legacy aliases */ { "pkg-add", RPM_OSTREE_BUILTIN_FLAG_HIDDEN, NULL, rpmostree_builtin_install }, diff --git a/src/app/rpmostree-builtin-temp-convert.c b/src/app/rpmostree-builtin-temp-convert.c new file mode 100644 index 0000000000..1fa93572f5 --- /dev/null +++ b/src/app/rpmostree-builtin-temp-convert.c @@ -0,0 +1,51 @@ +#include "config.h" +#include "libglnx.h" +#include "rpmostree-util.h" +#include "rpmostree-json-parsing.h" +#include "rpmostree-passwd-util.h" +#include "rpmostree-builtins.h" + +static char *opt_conversion_location; + + +static GOptionEntry conversion_option_entries[] = { + { "conversion_dir", 0, 0, G_OPTION_ARG_STRING, &opt_conversion_location, "Directory to convert", "CONVERSION_DIR"}, + { NULL } +}; + +// Temporarily take one argument --> mainly to convert the entries from /usr/lib/passwd into +// entries into sysusers.d +gboolean rpmostree_builtin_temp_convert (int argc, + char **argv, + RpmOstreeCommandInvocation *invocation, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GOptionContext) context = g_option_context_new (""); + if (!rpmostree_option_context_parse (context, + conversion_option_entries, + &argc, &argv, + invocation, + cancellable, + NULL, NULL, NULL, NULL, NULL, error)) + return FALSE; + + /* Test the output for conversion, right now we can already convert the content into one string conten. The next step would just be to write a function to write sysusers entries to a new place */ + const char* passwd_content = glnx_file_get_contents_utf8_at (AT_FDCWD, "/usr/lib/passwd", NULL, cancellable, error); + const char* group_content = glnx_file_get_contents_utf8_at (AT_FDCWD, "/usr/lib/group", NULL, cancellable, error); + + g_print ("The password content is %s\n", passwd_content); + g_print ("The group content is %s\n", group_content); + g_autoptr(GPtrArray) passwd_ents = rpmostree_passwd_data2passwdents (passwd_content); + g_autoptr(GPtrArray) group_ents = rpmostree_passwd_data2groupents (group_content); + g_autoptr(GPtrArray) sysusers_entries = NULL; + rpmostree_passwdents2sysusers (passwd_ents, &sysusers_entries, error); + rpmostree_groupents2sysusers (group_ents, &sysusers_entries, error); + + g_autofree char* sysuser_converted_content = NULL; + rpmostree_passwd_sysusers2char (sysusers_entries, &sysuser_converted_content, error); + + g_print("The content after conversion is %s\n", sysuser_converted_content); + + return TRUE; +} diff --git a/src/app/rpmostree-builtins.h b/src/app/rpmostree-builtins.h index 6efba51598..438d47857c 100644 --- a/src/app/rpmostree-builtins.h +++ b/src/app/rpmostree-builtins.h @@ -51,6 +51,7 @@ BUILTINPROTO(override); BUILTINPROTO(kargs); BUILTINPROTO(start_daemon); BUILTINPROTO(ex); +BUILTINPROTO(temp_convert); #undef BUILTINPROTO diff --git a/src/app/rpmostree-compose-builtin-tree.c b/src/app/rpmostree-compose-builtin-tree.c index 41927faad2..2ba2399f0b 100644 --- a/src/app/rpmostree-compose-builtin-tree.c +++ b/src/app/rpmostree-compose-builtin-tree.c @@ -1326,15 +1326,43 @@ impl_commit_tree (RpmOstreeTreeComposeContext *self, if (self->treefile) { g_autoptr(GFile) treefile_dirpath = g_file_get_parent (self->treefile_path); + g_autoptr(GPtrArray) sysuser_entries = NULL; if (!rpmostree_check_passwd (self->repo, self->rootfs_dfd, treefile_dirpath, self->treefile, - self->previous_checksum, + self->previous_checksum, &sysuser_entries, cancellable, error)) return glnx_prefix_error (error, "Handling passwd db"); if (!rpmostree_check_groups (self->repo, self->rootfs_dfd, treefile_dirpath, self->treefile, - self->previous_checksum, + self->previous_checksum, &sysuser_entries, cancellable, error)) return glnx_prefix_error (error, "Handling group db"); + + if (sysuser_entries) + { + g_autofree gchar *sysuser_content = NULL; + struct stat empty_stat; + const char *sysuser_folder = "usr/lib/sysusers.d"; + + if (!rpmostree_passwd_sysusers2char (sysuser_entries, + &sysuser_content, error)) + return glnx_prefix_error (error, "Handling sysuser conversion"); + + /* Do a deletion of original /usr/lib/sysusers.d/ to + * avoid duplication of existing sysuser entries */ + if (fstatat (self->rootfs_dfd, sysuser_folder, &empty_stat, AT_SYMLINK_NOFOLLOW) == 0) + if (!glnx_shutil_rm_rf_at (self->rootfs_dfd, sysuser_folder, cancellable, error)) + return FALSE; + + /* Creation of the converted sysuser entries into a conf file in + * sysuser folder */ + if (!glnx_ensure_dir (self->rootfs_dfd, sysuser_folder, 0755, error)) + return FALSE; + if (!glnx_file_replace_contents_at (self->rootfs_dfd, "usr/lib/sysusers.d/rpm-ostree-base.conf", + (guint8*)sysuser_content, -1, + GLNX_FILE_REPLACE_NODATASYNC, + cancellable, error)) + return FALSE; + } } /* See comment above */ diff --git a/src/libpriv/rpmostree-passwd-util.c b/src/libpriv/rpmostree-passwd-util.c index 834ed7cbab..3db1b413f4 100644 --- a/src/libpriv/rpmostree-passwd-util.c +++ b/src/libpriv/rpmostree-passwd-util.c @@ -359,6 +359,7 @@ rpmostree_check_passwd_groups (gboolean passwd, GFile *treefile_dirpath, JsonObject *treedata, const char *previous_commit, + GPtrArray **out_sysuser_entries, GCancellable *cancellable, GError **error) { @@ -386,7 +387,7 @@ rpmostree_check_passwd_groups (gboolean passwd, return TRUE; /* Note early return */ else if (g_str_equal (chk_type, "previous")) ; /* Handled below */ - else if (g_str_equal (chk_type, "file")) + else if (g_str_equal (chk_type, "file") || g_str_equal (chk_type, "sysusers")) { direct = _rpmostree_jsonutil_object_require_string_member (chk, "filename", @@ -491,7 +492,7 @@ rpmostree_check_passwd_groups (gboolean passwd, return TRUE; } } - else if (g_str_equal (chk_type, "file")) + else if (g_str_equal (chk_type, "file") || g_str_equal (chk_type, "sysusers")) { old_path = g_file_resolve_relative_path (treefile_dirpath, direct); old_contents = glnx_file_get_contents_utf8_at (AT_FDCWD, gs_file_get_path_cached (old_path), NULL, @@ -500,7 +501,7 @@ rpmostree_check_passwd_groups (gboolean passwd, return FALSE; } - if (g_str_equal (chk_type, "previous") || g_str_equal (chk_type, "file")) + if (g_str_equal (chk_type, "previous") || g_str_equal (chk_type, "file") || g_str_equal (chk_type, "sysusers")) { if (passwd) old_ents = rpmostree_passwd_data2passwdents (old_contents); @@ -681,6 +682,16 @@ rpmostree_check_passwd_groups (gboolean passwd, } } + /* Now, at the end of checking, if all goes correctly, we put entries into + * the array of sysusers */ + if (g_str_equal (chk_type, "sysusers")) + { + if (passwd) + return rpmostree_passwdents2sysusers (new_ents, out_sysuser_entries, error); + else + return rpmostree_groupents2sysusers (new_ents, out_sysuser_entries, error); + } + return TRUE; } @@ -693,11 +704,12 @@ rpmostree_check_passwd (OstreeRepo *repo, GFile *treefile_dirpath, JsonObject *treedata, const char *previous_commit, + GPtrArray **out_sysuser_entries, GCancellable *cancellable, GError **error) { return rpmostree_check_passwd_groups (TRUE, repo, rootfs_fd, treefile_dirpath, - treedata, previous_commit, + treedata, previous_commit, out_sysuser_entries, cancellable, error); } @@ -710,11 +722,12 @@ rpmostree_check_groups (OstreeRepo *repo, GFile *treefile_dirpath, JsonObject *treedata, const char *previous_commit, + GPtrArray **out_sysuser_entries, GCancellable *cancellable, GError **error) { return rpmostree_check_passwd_groups (FALSE, repo, rootfs_fd, treefile_dirpath, - treedata, previous_commit, + treedata, previous_commit, out_sysuser_entries, cancellable, error); } @@ -1032,7 +1045,7 @@ _data_from_json (int rootfs_dfd, if (!chk_type) return FALSE; - if (!g_str_equal (chk_type, "file")) + if (!g_str_equal (chk_type, "file") && !g_str_equal (chk_type, "sysusers")) return TRUE; const char *filename = diff --git a/src/libpriv/rpmostree-passwd-util.h b/src/libpriv/rpmostree-passwd-util.h index f72e360aa1..462e4b6df8 100644 --- a/src/libpriv/rpmostree-passwd-util.h +++ b/src/libpriv/rpmostree-passwd-util.h @@ -30,6 +30,7 @@ rpmostree_check_passwd (OstreeRepo *repo, GFile *treefile_path, JsonObject *treedata, const char *previous_commit, + GPtrArray **out_sysuser_entries, GCancellable *cancellable, GError **error); @@ -39,6 +40,7 @@ rpmostree_check_groups (OstreeRepo *repo, GFile *treefile_path, JsonObject *treedata, const char *previous_commit, + GPtrArray **out_sysuser_entries, GCancellable *cancellable, GError **error); diff --git a/src/libpriv/rpmostree-postprocess.c b/src/libpriv/rpmostree-postprocess.c index 510e031afc..c775e93bc3 100644 --- a/src/libpriv/rpmostree-postprocess.c +++ b/src/libpriv/rpmostree-postprocess.c @@ -982,9 +982,23 @@ rpmostree_postprocess_final (int rootfs_dfd, cancellable, error)) return FALSE; - /* NSS configuration to look at the new files */ - if (!replace_nsswitch (rootfs_dfd, cancellable, error)) - return glnx_prefix_error (error, "nsswitch replacement"); + gboolean is_sysuser_enabled = FALSE; + if (json_object_has_member (treefile, "check-passwd")) + { + JsonObject *chk = json_object_get_object_member (treefile, "check-passwd"); + if (!chk) + return glnx_throw (error, "%s is not an object", "check-passwd"); + const char *chk_type = _rpmostree_jsonutil_object_require_string_member (chk, "type", error); + if (!chk_type) + return FALSE; + is_sysuser_enabled = g_str_equal (chk_type, "sysusers"); + } + + /* Here, we check if sysuser option is enabled, if it is not, + * We will be writing NSS configuration to look at the new files */ + if (!is_sysuser_enabled) + if (!replace_nsswitch (rootfs_dfd, cancellable, error)) + return glnx_prefix_error (error, "nsswitch replacement"); if (selinux) { @@ -1922,10 +1936,10 @@ count_filesizes (int dfd, GError **error) { g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; - + if (!glnx_dirfd_iterator_init_at (dfd, path, TRUE, &dfd_iter, error)) return FALSE; - + while (TRUE) { struct dirent *dent = NULL;