[Pkg-shadow-devel] [Git][debian/adduser][master] 8 commits: introduce new systemcall_useradd

Marc Haber (@zugschlus) gitlab at salsa.debian.org
Wed Feb 19 17:41:07 GMT 2025



Marc Haber pushed to branch master at Debian / adduser


Commits:
cb02adde by Marc Haber at 2025-02-19T16:40:34+01:00
introduce new systemcall_useradd

- - - - -
d1d011ef by Marc Haber at 2025-02-19T16:40:57+01:00
fix variable names in systemcall and systemcall_or_warn

Git-Dch: ignore

- - - - -
cc406d31 by Marc Haber at 2025-02-19T18:09:15+01:00
use systemcall_useradd

Git-Dch: ignore

- - - - -
a436c8f4 by Marc Haber at 2025-02-19T18:09:17+01:00
use systemcall instead of &systemcall

Git-Dch: ignore

- - - - -
2d904580 by Marc Haber at 2025-02-19T18:09:17+01:00
use systemcall instead of @systemcall

Git-Dch: ignore

- - - - -
561b7c9b by Marc Haber at 2025-02-19T18:09:17+01:00
re-work call of passwd and exit code evaluation

Git-Dch: ignore

- - - - -
168d0a5d by Marc Haber at 2025-02-19T18:09:17+01:00
fixup! introduce new systemcall_useradd

- - - - -
f9a73dfc by Marc Haber at 2025-02-19T18:09:45+01:00
eliminate more of & function calls

Git-Dch: ignore

- - - - -


3 changed files:

- AdduserCommon.pm
- adduser
- deluser


Changes:

=====================================
AdduserCommon.pm
=====================================
@@ -77,6 +77,7 @@ use constant {
     'get_group_members',
     'read_config',
     'read_pool',
+    'systemcall_useradd',
     'systemcall',
     'systemcall_or_warn',
     'systemcall_silent',
@@ -305,15 +306,46 @@ sub get_group_members
     return @members;
 }
 
+sub systemcall_useradd {
+    my $name_check_level = shift;
+    my $command = join(' ', @_);
+    my $ret;
+    log_debug( "executing systemcall_useradd (%s): %s", $name_check_level, $command );
+    $ret = system(@_);
+    if ($ret != 0) {
+        my $exitcode = $ret>>8;
+        if ($exitcode != 0) {
+            if ($exitcode == 19 ) {
+                # we should never get here. It is our expectation that we catch
+                # an invalid user name before useradd gets to reject it. So
+                # we consider getting here a bug in our regexps. We can safely
+                # bomb out here.
+                if( $name_check_level == 2 ) {
+                    log_warn( mtx("`%s' refused the given user name, but --allow-all-names is given. Continueing."), $command );
+                    return( RET_INVALID_NAME_FROM_USERADD );
+                } else {
+                    log_err( mtx("`%s' refused the given user name. This is a bug in adduser. Please file a bug report."), $command );
+                    exit( RET_INVALID_NAME_FROM_USERADD ); 
+                };
+            } else {
+                log_fatal( mtx("`%s' returned error code %d. Exiting."), $command, $exitcode );
+                exit( RET_SYSTEMCALL_ERROR );
+            }
+        }
+        log_fatal( mtx("`%s' exited from signal %d. Exiting."), $command, $ret&127 );
+        exit( RET_SYSTEMCALL_SIGNAL );
+    }
+}
+
 sub systemcall {
-    my $c = join(' ', @_);
+    my $command = join(' ', @_);
     log_debug( "executing systemcall: %s", $command );
     if (system(@_)) {
         if ($?>>8) {
-            log_fatal( mtx("`%s' returned error code %d. Exiting."), $c, $?>>8 );
+            log_fatal( mtx("`%s' returned error code %d. Exiting."), $command, $?>>8 );
             exit( RET_SYSTEMCALL_ERROR );
         }
-        log_fatal( mtx("`%s' exited from signal %d. Exiting."), $c, $?&127 );
+        log_fatal( mtx("`%s' exited from signal %d. Exiting."), $command, $?&127 );
         exit( RET_SYSTEMCALL_SIGNAL );
     }
 }
@@ -322,16 +354,17 @@ sub systemcall_or_warn {
     my $command = join(' ', @_);
     log_debug( "executing systemcall_or_warn: %s", $command );
     system(@_);
+    my $ret = $?;
 
-    if ($? == -1) {
+    if ($ret == -1) {
         log_warn( mtx("`%s' failed to execute. %s. Continuing."), $command, $! );
     } elsif ($? & 127) {
-        log_warn( mtx("`%s' killed by signal %d. Continuing."), $command, ($? & 127) );
+        log_warn( mtx("`%s' killed by signal %d. Continuing."), $command, ($ret & 127) );
     } elsif ($? >> 8) {
-        log_warn( mtx("`%s' failed with status %d. Continuing."), $command, ($? >> 8) );
+        log_warn( mtx("`%s' failed with status %d. Continuing."), $command, ($ret >> 8) );
     }
 
-    return $?;
+    return $ret;
 }
 
 sub systemcall_silent {


=====================================
adduser
=====================================
@@ -128,6 +128,7 @@ my %uid_pool;
 my %gid_pool;
 my %reserved_uid_pool;
 my %reserved_gid_pool;
+my $returnvalue = RET_OK;
 
 our @names;
 
@@ -458,10 +459,13 @@ if ($action eq "addsysgroup") {
 
 
     log_info( mtx("Adding group `%s' (GID %d) ..."), $new_name, $gid_option);
-    my $groupadd = &which('groupadd');
-    &systemcall($groupadd, '-g', $gid_option, $new_name);
+    my $groupadd = which('groupadd');
+    $ret = systemcall_useradd($name_check_level, $groupadd, '-g', $gid_option, $new_name);
+    if( $ret == RET_INVALID_NAME_FROM_USERADD ) {
+        $returnvalue = RET_INVALID_NAME_FROM_USERADD;
+    }
     release_lock(0);
-    exit( RET_OK );
+    exit( $returnvalue );
 }
 
 
@@ -500,10 +504,13 @@ if ($action eq "addgroup") {
     }
 
     log_info( mtx("Adding group `%s' (GID %d) ..."), $new_name, $gid_option);
-    my $groupadd = &which('groupadd');
-    &systemcall($groupadd, '-g', $gid_option, $new_name);
+    my $groupadd = which('groupadd');
+    my $ret = systemcall_useradd($name_check_level, $groupadd, '-g', $gid_option, $new_name);
+    if( $ret == RET_INVALID_NAME_FROM_USERADD ) {
+        $returnvalue = RET_INVALID_NAME_FROM_USERADD;
+    }
     release_lock(0);
-    exit( RET_OK );
+    exit( $returnvalue );
 }
 
 
@@ -529,10 +536,10 @@ if ($action eq 'addusertogroup') {
     log_info( mtx("Adding user `%s' to group `%s' ..."), $existing_user, $existing_group );
 
     acquire_lock();
-    &systemcall('/usr/sbin/usermod', '-a', '-G', $existing_group, $existing_user);
+    systemcall('/usr/sbin/usermod', '-a', '-G', $existing_group, $existing_user);
     release_lock();
 
-    exit( RET_OK );
+    exit( $returnvalue );
 }
 
 ################
@@ -615,8 +622,11 @@ if ($action eq "addsysuser") {
     if ($make_group_also && !egetgrnam($new_name)) {
         log_info( mtx("Adding new group `%s' (GID %d) ..."), $new_name, $gid_option );
         $undogroup = $new_name;
-        my $groupadd = &which('groupadd');
-        &systemcall($groupadd, '-g', $gid_option, $new_name);
+        my $groupadd = which('groupadd');
+        my $ret = systemcall_useradd($name_check_level, $groupadd, '-g', $gid_option, $new_name);
+        if( $ret == RET_INVALID_NAME_FROM_USERADD ) {
+            $returnvalue = RET_INVALID_NAME_FROM_USERADD;
+        }
     }
 
     log_info( mtx("Adding new user `%s' (UID %d) with group `%s' ..."),
@@ -627,7 +637,10 @@ if ($action eq "addsysuser") {
     $shell = $special_shell || $uid_pool{$new_name}{'shell'} || '/usr/sbin/nologin';
     $undouser = $new_name;
 
-    &systemcall('/usr/sbin/useradd', '-r',
+    my $useradd = which('useradd');
+    my $ret = systemcall_useradd($name_check_level, 
+        $useradd,
+        '-r',
         '-K', sprintf('SYS_UID_MIN=%d', $new_firstuid || $config{'first_system_uid'}),
         '-K', sprintf('SYS_UID_MAX=%d', $new_lastuid || $config{'last_system_uid'}),
         '-d', $home_dir,
@@ -635,20 +648,22 @@ if ($action eq "addsysuser") {
         '-s', $shell,
         '-u', $new_uid,
         $new_name);
-    ##+# TODO: Catch exit code 19 "invalid user name"
+    if( $ret == RET_INVALID_NAME_FROM_USERADD ) {
+        $returnvalue = RET_INVALID_NAME_FROM_USERADD;
+    }
 
     release_lock(0);
 
     if (defined($new_comment)) {
-        &ch_comment($new_comment);
+        ch_comment($new_comment);
     } elsif ($uid_pool{$new_name}{'comment'}) {
-        &ch_comment($uid_pool{$new_name}{'comment'});
+        ch_comment($uid_pool{$new_name}{'comment'});
     }
 
     $primary_gid = $gid_option;
     create_homedir(0);
 
-    exit( RET_OK );
+    exit( $returnvalue );
 }
 
 
@@ -835,16 +850,20 @@ if ($action eq "adduser") {
     log_debug ("make_group_also %s", $make_group_also );
     if ($make_group_also) {
         $undogroup = $new_name;
-        my $groupadd = &which('groupadd');
+        my $groupadd = which('groupadd');
+        my $ret;
         if( defined( $primary_gid ) ) {
            log_info( mtx("Adding new group `%s' (%d) ..."), $new_name, $primary_gid);
-           &systemcall($groupadd, '-g', $primary_gid, $new_name);
+           $ret = systemcall_useradd($name_check_level, $groupadd, '-g', $primary_gid, $new_name);
         } else {
            log_info( mtx("Adding new group `%s' (new group ID) ..."), $new_name);
-           &systemcall($groupadd, $new_name);
+           $ret = systemcall_useradd($name_check_level, $groupadd, $new_name);
            $primary_gid = egetgrnam($new_name);
            log_info( mtx("new group '%s' created with GID %d"), $new_name, $primary_gid );
         }
+        if( $ret == RET_INVALID_NAME_FROM_USERADD ) {
+            $returnvalue = RET_INVALID_NAME_FROM_USERADD;
+        }
     }
 
     {
@@ -860,10 +879,17 @@ if ($action eq "adduser") {
     }
     log_debug( "creating new user %s with home_dir %s and shell %s", $new_name, $home_dir, $shell );
     $undouser = $new_name;
-    my $useradd = &which('useradd');
-    &systemcall($useradd, '-d', $home_dir, '-g', $primary_gid, '-s',
-                $shell, '-u', $new_uid, $new_name);
-    ##+# TODO: Catch exit code 19 "invalid user name"
+    my $useradd = which('useradd');
+    my $ret = systemcall_useradd($name_check_level,
+        $useradd,
+        '-d', $home_dir,
+        '-g', $primary_gid,
+        '-s', $shell,
+        '-u', $new_uid,
+        $new_name);
+    if( $ret == RET_INVALID_NAME_FROM_USERADD ) {
+        $returnvalue = RET_INVALID_NAME_FROM_USERADD;
+    }
 
     create_homedir (1); # copy skeleton data
 
@@ -872,20 +898,30 @@ if ($action eq "adduser") {
     my $noexpr = langinfo(NOEXPR());
     if ($ask_passwd) {
         PASSWD: for (;;) {
-            my $passwd = &which('passwd');
-            # do _not_ use systemcall() here, since systemcall() dies on
-            # non-zero exit code and we need to do special handling here!
-            system($passwd, $new_name);
-            my $ok = $?>>8;
+            my $passwd = which('passwd');
+            my $ok = systemcall_or_warn($passwd, $new_name);
+            $ok = $ok >> 8;
+            log_debug( "systemcall_or_warn %s %s return value %s", $passwd, $new_name, $ok);
             if ($ok != 0) {
                 my $answer;
                 # hm, error, should we break now?
-                log_warn( mtx("Permission denied")) if ($ok == 1);
-                log_warn( mtx("invalid combination of options")) if ($ok == 2);
-                log_warn( mtx("unexpected failure, nothing done")) if ($ok == 3);
-                log_warn( mtx("unexpected failure, passwd file missing")) if ($ok == 4);
-                log_warn( mtx("passwd file busy, try again")) if ($ok == 5);
-                log_warn( mtx("invalid argument to option")) if ($ok == 6);
+                if ($ok == 1) {
+                    log_warn( mtx("Permission denied"));
+                } elsif ($ok == 2) {
+                    log_warn( mtx("invalid combination of options"));
+                } elsif ($ok == 3) {
+                    log_warn( mtx("unexpected failure, nothing done"));
+                } elsif ($ok == 4) {
+                    log_warn( mtx("unexpected failure, passwd file missing"));
+                } elsif ($ok == 5) {
+                    log_warn( mtx("passwd file busy, try again"));
+                } elsif ($ok == 6) {
+                    log_warn( mtx("invalid argument to option"));
+                } elsif ($ok == 10) {
+                    log_warn( mtx("wrong password given or password retyped incorrectly"));
+                } else {
+                    log_warn( mtx("unexpected return code %s given from passwd"), $ok );
+                }
 
                 # Translators: [y/N] has to be replaced by values defined in your
                 # locale.  You can see by running "locale noexpr" which regular
@@ -904,15 +940,15 @@ if ($action eq "adduser") {
     }
 
     if (defined($new_comment)) {
-        &ch_comment($new_comment);
+        ch_comment($new_comment);
     } elsif ($uid_pool{$new_name}{'comment'}) {
-        &ch_comment($uid_pool{$new_name}{'comment'});
+        ch_comment($uid_pool{$new_name}{'comment'});
     } else {
         my $noexpr = langinfo(NOEXPR());
         my $yesexpr = langinfo(YESEXPR());
         CHFN: for (;;) {
             my $chfn = &which('chfn');
-            &systemcall($chfn, $new_name);
+            systemcall($chfn, $new_name);
             # Translators: [y/N] has to be replaced by values defined in your
             # locale.  You can see by running "locale yesexpr" which regular
             # expression will be checked to find positive answer.
@@ -947,7 +983,7 @@ if ($action eq "adduser") {
 
             log_info( mtx("Adding user `%s' to group `%s' ..."), $new_name, $newgrp );
             my $gpasswd = &which('gpasswd');
-            &systemcall($gpasswd, '-M',
+            systemcall($gpasswd, '-M',
                         join(',', get_group_members($newgrp), $new_name),
                         $newgrp);
         }
@@ -957,14 +993,14 @@ if ($action eq "adduser") {
     if ($config{"quotauser"}) {
         log_info( mtx("Setting quota for user `%s' to values of user `%s' ..."), $new_name, $config{quotauser} );
         my $edquota = &which('edquota');
-        &systemcall($edquota, '-p', $config{quotauser}, $new_name);
+        systemcall($edquota, '-p', $config{quotauser}, $new_name);
     }
 
-    &systemcall('/usr/local/sbin/adduser.local', $new_name, $new_uid,
+    systemcall('/usr/local/sbin/adduser.local', $new_name, $new_uid,
             $primary_gid, $home_dir) if (-x "/usr/local/sbin/adduser.local");
     release_lock(0);
 
-    exit( RET_OK );
+    exit( $returnvalue );
 }
 
 #
@@ -1424,15 +1460,15 @@ sub ch_comment {
         my($comment_name,$comment_room,$comment_work,$comment_home,$comment_other)
           = split(/,/,$comment);
  
-        &systemcall($chfn, '-f', $comment_name, '-r', $comment_room, $new_name);
-        &systemcall($chfn,'-w',$comment_work,$new_name)
+        systemcall($chfn, '-f', $comment_name, '-r', $comment_room, $new_name);
+        systemcall($chfn,'-w',$comment_work,$new_name)
           if(defined($comment_work));
-        &systemcall($chfn,'-h',$comment_home,$new_name)
+        systemcall($chfn,'-h',$comment_home,$new_name)
           if(defined($comment_home));
-        &systemcall($chfn,'-o',$comment_other,$new_name)
+        systemcall($chfn,'-o',$comment_other,$new_name)
           if(defined($comment_other));
     } else {
-        &systemcall($chfn, '-f', $comment, $new_name);
+        systemcall($chfn, '-f', $comment, $new_name);
     }
 }
 
@@ -1449,15 +1485,15 @@ sub user_is_member {
 sub cleanup {
     if ($undohome) {
         log_info( mtx("Removing directory `%s' ..."), $undohome);
-        &systemcall('rm', '-rf', $undohome);
+        systemcall('rm', '-rf', $undohome);
     }
     if ($undouser) {
         log_info( mtx("Removing user `%s' ..."), $undouser);
-        &systemcall('userdel', $undouser);
+        systemcall('userdel', $undouser);
     }
     if ($undogroup) {
         log_info( mtx("Removing group `%s' ..."), $undogroup);
-        &systemcall('groupdel', $undogroup);
+        systemcall('groupdel', $undogroup);
     }
     exit( RET_ADDUSER_ABORTED );
 }


=====================================
deluser
=====================================
@@ -376,7 +376,7 @@ if($action eq "deluser") {
             $backup_name .= $config{'backup_suffix'};
             $backup_name = sanitize_string( $backup_name, simplepathre );
             log_debug( "backup_name = %s", $backup_name );
-            &systemcall($tar, "--directory", "/", "--auto-compress", "-cf", $backup_name, "--files-from", $filesfilename);
+            systemcall($tar, "--directory", "/", "--auto-compress", "-cf", $backup_name, "--files-from", $filesfilename);
             chmod 0600, $backup_name;
             my $rootid = 0;
             chown $rootid, $rootid, $backup_name;
@@ -395,8 +395,8 @@ if($action eq "deluser") {
     if (-x '/usr/bin/crontab') {
         log_info( mtx("Removing crontab ...") );
 
-        if (&systemcall_silent('/usr/bin/crontab', '-u', $user, '-l') == 0) {
-            &systemcall_or_warn('/usr/bin/crontab', '-u', $user, '-r');
+        if (systemcall_silent('/usr/bin/crontab', '-u', $user, '-l') == 0) {
+            systemcall_or_warn('/usr/bin/crontab', '-u', $user, '-r');
         }
     } else {
         log_warn( mtx("`%s' not executed. Skipping crontab removal. Package `cron' required."),
@@ -405,10 +405,10 @@ if($action eq "deluser") {
 
     log_info( mtx("Removing user `%s' ..."), $user);
     acquire_lock();
-    &systemcall('/usr/sbin/userdel', $user);
+    systemcall('/usr/sbin/userdel', $user);
     release_lock();
 
-    &systemcall('/usr/local/sbin/deluser.local', $user, $pw_uid,
+    systemcall('/usr/local/sbin/deluser.local', $user, $pw_uid,
         $pw_gid, $pw_homedir) if (-x "/usr/local/sbin/deluser.local");
 
     exit( RET_OK );
@@ -448,7 +448,7 @@ if ($action eq 'delgroup') {
     log_info( mtx("Removing group `%s' ..."), $group );
     my $groupdel = &which('groupdel');
     acquire_lock();
-    &systemcall($groupdel,$group);
+    systemcall($groupdel,$group);
     release_lock();
     exit 0;
 }
@@ -490,7 +490,7 @@ if($action eq 'deluserfromgroup')
     log_info( mtx("Removing user `%s' from group `%s' ..."), $user, $group );
 
     acquire_lock();
-    &systemcall('/usr/bin/gpasswd', '-M', join(',', @members), $group);
+    systemcall('/usr/bin/gpasswd', '-M', join(',', @members), $group);
     release_lock();
 }
 
@@ -561,7 +561,7 @@ sub check_backup_suffix {
     }
     my $filename = '/tmp/deluser-check.tar';
     my $testfile = 'usr/sbin/deluser';
-    &systemcall_silent_error($tar, '--auto-compress', '--directory', '/', '-cf', $filename.$suffix, $testfile);
+    systemcall_silent_error($tar, '--auto-compress', '--directory', '/', '-cf', $filename.$suffix, $testfile);
 
     if ($?) {
         # compressor recognized, not available
@@ -569,7 +569,7 @@ sub check_backup_suffix {
         $suffix = '.gz';
     } else {
         # no error, check if compressed
-        &systemcall_silent($tar, '--directory', '/', '-cf', $filename, $testfile);
+        systemcall_silent($tar, '--directory', '/', '-cf', $filename, $testfile);
 
         my @zstat = stat($filename.$suffix);
         my @ustat = stat($filename);



View it on GitLab: https://salsa.debian.org/debian/adduser/-/compare/1aae1ef35eba09c04237868ada66594a8e557773...f9a73dfc70a4779c6ccd8db13bb07f0e720690de

-- 
View it on GitLab: https://salsa.debian.org/debian/adduser/-/compare/1aae1ef35eba09c04237868ada66594a8e557773...f9a73dfc70a4779c6ccd8db13bb07f0e720690de
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-shadow-devel/attachments/20250219/bc846c25/attachment-0001.htm>


More information about the Pkg-shadow-devel mailing list