summaryrefslogtreecommitdiffstats
path: root/lib/root_flag.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-26 16:18:36 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-26 16:18:36 +0000
commit6c3ea4f47ea280811a7fe53a22f7832e4533c9ec (patch)
tree3d7ed5da23b5dbf6f9e450dfb61642832249c31e /lib/root_flag.c
parentAdding upstream version 1:4.13+dfsg1. (diff)
downloadshadow-upstream/1%4.15.2.tar.xz
shadow-upstream/1%4.15.2.zip
Adding upstream version 1:4.15.2.upstream/1%4.15.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/root_flag.c')
-rw-r--r--lib/root_flag.c108
1 files changed, 108 insertions, 0 deletions
diff --git a/lib/root_flag.c b/lib/root_flag.c
new file mode 100644
index 0000000..5572831
--- /dev/null
+++ b/lib/root_flag.c
@@ -0,0 +1,108 @@
+/*
+ * SPDX-FileCopyrightText: 2011 , Julian Pidancet
+ * SPDX-FileCopyrightText: 2011 , Nicolas François
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <config.h>
+
+#ident "$Id$"
+
+#include <stdio.h>
+#include <assert.h>
+#include "defines.h"
+#include "prototypes.h"
+/*@-exitarg@*/
+#include "exitcodes.h"
+#include "shadowlog.h"
+
+static void change_root (const char* newroot);
+
+/*
+ * process_root_flag - chroot if given the --root option
+ *
+ * This shall be called before accessing the passwd, group, shadow,
+ * gshadow, useradd's default, login.defs files (non exhaustive list)
+ * or authenticating the caller.
+ *
+ * The audit, syslog, or locale files shall be open before
+ */
+extern void process_root_flag (const char* short_opt, int argc, char **argv)
+{
+ /*
+ * Parse the command line options.
+ */
+ int i;
+ const char *newroot = NULL, *val;
+
+ for (i = 0; i < argc; i++) {
+ val = NULL;
+ if ( (strcmp (argv[i], "--root") == 0)
+ || ((strncmp (argv[i], "--root=", 7) == 0)
+ && (val = argv[i] + 7))
+ || (strcmp (argv[i], short_opt) == 0)) {
+ if (NULL != newroot) {
+ fprintf (log_get_logfd(),
+ _("%s: multiple --root options\n"),
+ log_get_progname());
+ exit (E_BAD_ARG);
+ }
+
+ if (val) {
+ newroot = val;
+ } else if (i + 1 == argc) {
+ fprintf (log_get_logfd(),
+ _("%s: option '%s' requires an argument\n"),
+ log_get_progname(), argv[i]);
+ exit (E_BAD_ARG);
+ } else {
+ newroot = argv[++ i];
+ }
+ }
+ }
+
+ if (NULL != newroot) {
+ change_root (newroot);
+ }
+}
+
+static void change_root (const char* newroot)
+{
+ /* Drop privileges */
+ if ( (setregid (getgid (), getgid ()) != 0)
+ || (setreuid (getuid (), getuid ()) != 0)) {
+ fprintf (log_get_logfd(), _("%s: failed to drop privileges (%s)\n"),
+ log_get_progname(), strerror (errno));
+ exit (EXIT_FAILURE);
+ }
+
+ if ('/' != newroot[0]) {
+ fprintf (log_get_logfd(),
+ _("%s: invalid chroot path '%s', only absolute paths are supported.\n"),
+ log_get_progname(), newroot);
+ exit (E_BAD_ARG);
+ }
+
+ if (access (newroot, F_OK) != 0) {
+ fprintf(log_get_logfd(),
+ _("%s: cannot access chroot directory %s: %s\n"),
+ log_get_progname(), newroot, strerror (errno));
+ exit (E_BAD_ARG);
+ }
+
+ if (chroot (newroot) != 0) {
+ fprintf(log_get_logfd(),
+ _("%s: unable to chroot to directory %s: %s\n"),
+ log_get_progname(), newroot, strerror (errno));
+ exit (E_BAD_ARG);
+ }
+
+ if (chdir ("/") != 0) {
+ fprintf(log_get_logfd(),
+ _("%s: cannot chdir in chroot directory %s: %s\n"),
+ log_get_progname(), newroot, strerror (errno));
+ exit (E_BAD_ARG);
+ }
+}
+