]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
useradd/usermod: add --selinux-range argument
authorChristian Göttsche <cgzones@googlemail.com>
Sat, 1 Apr 2023 12:34:56 +0000 (14:34 +0200)
committerIker Pedrosa <ikerpedrosam@gmail.com>
Wed, 19 Apr 2023 07:19:19 +0000 (09:19 +0200)
Add a command line argument to useradd(8) and usermod(8) to specify the
MLS range for a SELinux user mapping.

Improves: #676

lib/prototypes.h
lib/semanage.c
man/useradd.8.xml
man/usermod.8.xml
src/useradd.c
src/usermod.c

index 21df6f615c89c5cdb7a53b9cb5e859c8e637f018..012652a9e841fdcd112c1fea5f9374015867b72d 100644 (file)
@@ -385,7 +385,7 @@ extern int check_selinux_permit (const char *perm_name);
 
 /* semanage.c */
 #ifdef WITH_SELINUX
-extern int set_seuser(const char *login_name, const char *seuser_name);
+extern int set_seuser(const char *login_name, const char *seuser_name, const char *serange);
 extern int del_seuser(const char *login_name);
 #endif
 
index bbb3f9937d9bbc40ae95abf85cc4d42a6079522f..5d336b084969d55e8ab3c5a61037b81e80bd41e3 100644 (file)
@@ -105,7 +105,8 @@ fail:
 static int semanage_user_mod (semanage_handle_t *handle,
                               semanage_seuser_key_t *key,
                               const char *login_name,
-                              const char *seuser_name)
+                              const char *seuser_name,
+                              const char *serange)
 {
        int ret;
        semanage_seuser_t *seuser = NULL;
@@ -118,6 +119,17 @@ static int semanage_user_mod (semanage_handle_t *handle,
                goto done;
        }
 
+       if (serange && semanage_mls_enabled(handle)) {
+               ret = semanage_seuser_set_mlsrange (handle, seuser, serange);
+               if (ret != 0) {
+                       fprintf (shadow_logfd,
+                                _("Could not set serange for %s to %s\n"),
+                                login_name, serange);
+                       ret = 1;
+                       goto done;
+               }
+       }
+
        ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
        if (ret != 0) {
                fprintf (shadow_logfd,
@@ -146,7 +158,8 @@ done:
 static int semanage_user_add (semanage_handle_t *handle,
                              semanage_seuser_key_t *key,
                              const char *login_name,
-                             const char *seuser_name)
+                             const char *seuser_name,
+                             const char *serange)
 {
        int ret;
        semanage_seuser_t *seuser = NULL;
@@ -167,6 +180,17 @@ static int semanage_user_add (semanage_handle_t *handle,
                goto done;
        }
 
+       if (serange && semanage_mls_enabled(handle)) {
+               ret = semanage_seuser_set_mlsrange (handle, seuser, serange);
+               if (ret != 0) {
+                       fprintf (shadow_logfd,
+                                _("Could not set serange for %s to %s\n"),
+                                login_name, serange);
+                       ret = 1;
+                       goto done;
+               }
+       }
+
        ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
        if (ret != 0) {
                fprintf (shadow_logfd,
@@ -192,7 +216,7 @@ done:
 }
 
 
-int set_seuser (const char *login_name, const char *seuser_name)
+int set_seuser (const char *login_name, const char *seuser_name, const char *serange)
 {
        semanage_handle_t *handle = NULL;
        semanage_seuser_key_t *key = NULL;
@@ -226,7 +250,7 @@ int set_seuser (const char *login_name, const char *seuser_name)
        }
 
        if (0 != seuser_exists) {
-               ret = semanage_user_mod (handle, key, login_name, seuser_name);
+               ret = semanage_user_mod (handle, key, login_name, seuser_name, serange);
                if (ret != 0) {
                        fprintf (shadow_logfd,
                                 _("Cannot modify SELinux user mapping\n"));
@@ -234,7 +258,7 @@ int set_seuser (const char *login_name, const char *seuser_name)
                        goto done;
                }
        } else {
-               ret = semanage_user_add (handle, key, login_name, seuser_name);
+               ret = semanage_user_add (handle, key, login_name, seuser_name, serange);
                if (ret != 0) {
                        fprintf (shadow_logfd,
                                 _("Cannot add SELinux user mapping\n"));
index 05e939a643a59244611fd49d3892680ec27d0ce9..51705285c64cb879f745689780f9c0fffe296354 100644 (file)
        <listitem>
          <para>
            defines the SELinux user for the new account. Without this
-           option, SELinux uses the default user. Note that the
+           option, SELinux uses the default user. Note that the
            shadow system doesn't store the selinux-user, it uses
            <citerefentry><refentrytitle>semanage</refentrytitle>
            <manvolnum>8</manvolnum></citerefentry> for that.
          </para>
        </listitem>
       </varlistentry>
+      <varlistentry>
+       <term>
+         <option>--selinux-range</option>&nbsp;<replaceable>SERANGE</replaceable>
+       </term>
+       <listitem>
+         <para>
+           defines the SELinux MLS range for the new account. Without this
+           option, SELinux uses the default range. Note that the
+           shadow system doesn't store the selinux-range, it uses
+           <citerefentry><refentrytitle>semanage</refentrytitle>
+           <manvolnum>8</manvolnum></citerefentry> for that.
+         </para>
+         <para>
+           This option is only valid if the <option>-Z</option> (or
+           <option>--selinux-user</option>) option is specified.
+         </para>
+       </listitem>
+      </varlistentry>
     </variablelist>
 
     <refsect2 id='changing_the_default_values'>
index 78092898dab229d75745fbd3e86cd5db66e1110d..349248b6bbf2c6c5ff99fbfe26342e861e3c4712 100644 (file)
          </para>
        </listitem>
       </varlistentry>
+      <varlistentry>
+       <term>
+         <option>--selinux-range</option>&nbsp;<replaceable>SERANGE</replaceable>
+       </term>
+       <listitem>
+         <para>
+           defines the SELinux MLS range for the new account.
+           Note that the shadow system doesn't store the selinux-range,
+           it uses <citerefentry><refentrytitle>semanage</refentrytitle>
+           <manvolnum>8</manvolnum></citerefentry> for that.
+         </para>
+         <para>
+           This option is only valid if the <option>-Z</option> (or
+           <option>--selinux-user</option>) option is specified.
+         </para>
+       </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
index c0d8eda9bc3f35950fe0f7d500b3e65d8e47de43..152b4e53507a4d7b145129b5e08c434082dee57e 100644 (file)
@@ -113,6 +113,7 @@ static const char *prefix_user_home = NULL;
 
 #ifdef WITH_SELINUX
 static /*@notnull@*/const char *user_selinux = "";
+static const char *user_selinux_range = NULL;
 #endif                         /* WITH_SELINUX */
 
 static long user_expire = -1;
@@ -997,6 +998,7 @@ static void usage (int status)
        (void) fputs (_("  -U, --user-group              create a group with the same name as the user\n"), usageout);
 #ifdef WITH_SELINUX
        (void) fputs (_("  -Z, --selinux-user SEUSER     use a specific SEUSER for the SELinux user mapping\n"), usageout);
+       (void) fputs (_("      --selinux-range SERANGE   use a specific MLS range for the SELinux user mapping\n"), usageout);
 #endif                         /* WITH_SELINUX */
        (void) fputs ("\n", usageout);
        exit (status);
@@ -1280,6 +1282,7 @@ static void process_flags (int argc, char **argv)
                        {"user-group",     no_argument,       NULL, 'U'},
 #ifdef WITH_SELINUX
                        {"selinux-user",   required_argument, NULL, 'Z'},
+                       {"selinux-range",  required_argument, NULL, 202},
 #endif                         /* WITH_SELINUX */
                        {NULL, 0, NULL, '\0'}
                };
@@ -1529,6 +1532,9 @@ static void process_flags (int argc, char **argv)
                                        exit (E_BAD_ARG);
                                }
                                break;
+                       case 202:
+                               user_selinux_range = optarg;
+                               break;
 #endif                         /* WITH_SELINUX */
                        default:
                                usage (E_USAGE);
@@ -1576,6 +1582,14 @@ static void process_flags (int argc, char **argv)
                         Prog, "-m", "-M");
                usage (E_USAGE);
        }
+#ifdef WITH_SELINUX
+       if (user_selinux_range && !Zflg) {
+               fprintf (stderr,
+                        _("%s: %s flag is only allowed with the %s flag\n"),
+                        Prog, "--selinux-range", "--selinux-user");
+               usage (E_USAGE);
+       }
+#endif                         /* WITH_SELINUX */
 
        /*
         * Either -D or username is required. Defaults can be set with -D
@@ -2760,7 +2774,7 @@ int main (int argc, char **argv)
 
 #ifdef WITH_SELINUX
        if (Zflg) {
-               if (set_seuser (user_name, user_selinux) != 0) {
+               if (set_seuser (user_name, user_selinux, user_selinux_range) != 0) {
                        fprintf (stderr,
                                 _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"),
                                 Prog, user_name, user_selinux);
index 05cc28fbadb8fc98eab470fff3f7b1975a4ad6a6..87c93d93c48bb6955ca90aa0190ca58ffe983fcd 100644 (file)
@@ -100,6 +100,7 @@ static char *user_newhome;
 static char *user_shell;
 #ifdef WITH_SELINUX
 static const char *user_selinux = "";
+static const char *user_selinux_range = NULL;
 #endif                         /* WITH_SELINUX */
 static char *user_newshell;
 static long user_expire;
@@ -405,6 +406,7 @@ usage (int status)
 #endif                         /* ENABLE_SUBIDS */
 #ifdef WITH_SELINUX
        (void) fputs (_("  -Z, --selinux-user SEUSER     new SELinux user mapping for the user account\n"), usageout);
+       (void) fputs (_("      --selinux-range SERANGE   new SELinux MLS range for the user account\n"), usageout);
 #endif                         /* WITH_SELINUX */
        (void) fputs ("\n", usageout);
        exit (status);
@@ -1004,7 +1006,8 @@ static void process_flags (int argc, char **argv)
                        {"del-subgids",  required_argument, NULL, 'W'},
 #endif                         /* ENABLE_SUBIDS */
 #ifdef WITH_SELINUX
-                       {"selinux-user", required_argument, NULL, 'Z'},
+                       {"selinux-user",  required_argument, NULL, 'Z'},
+                       {"selinux-range", required_argument, NULL, 202},
 #endif                         /* WITH_SELINUX */
                        {NULL, 0, NULL, '\0'}
                };
@@ -1214,6 +1217,9 @@ static void process_flags (int argc, char **argv)
                                        exit (E_BAD_ARG);
                                }
                                break;
+                       case 202:
+                               user_selinux_range = optarg;
+                               break;
 #endif                         /* WITH_SELINUX */
                        default:
                                usage (E_USAGE);
@@ -1354,6 +1360,15 @@ static void process_flags (int argc, char **argv)
                usage (E_USAGE);
        }
 
+#ifdef WITH_SELINUX
+       if (user_selinux_range && !Zflg) {
+               fprintf (stderr,
+                        _("%s: %s flag is only allowed with the %s flag\n"),
+                        Prog, "--selinux-range", "--selinux-user");
+               usage (E_USAGE);
+       }
+#endif                         /* WITH_SELINUX */
+
        if (user_newid == user_id) {
                uflg = false;
                oflg = false;
@@ -2304,7 +2319,7 @@ int main (int argc, char **argv)
 #ifdef WITH_SELINUX
        if (Zflg) {
                if ('\0' != *user_selinux) {
-                       if (set_seuser (user_name, user_selinux) != 0) {
+                       if (set_seuser (user_name, user_selinux, user_selinux_range) != 0) {
                                fprintf (stderr,
                                         _("%s: warning: the user name %s to %s SELinux user mapping failed.\n"),
                                         Prog, user_name, user_selinux);