From gitlab at salsa.debian.org Sat Nov 1 07:28:59 2025 From: gitlab at salsa.debian.org (Marc Haber (@zugschlus)) Date: Sat, 01 Nov 2025 07:28:59 +0000 Subject: [Pkg-shadow-devel] [Git][debian/adduser] Pushed new branch wip/1099734 Message-ID: <6905b6bbd2e38_13a76dc3461449537c@godard.mail> Marc Haber pushed new branch wip/1099734 at Debian / adduser -- View it on GitLab: https://salsa.debian.org/debian/adduser/-/tree/wip/1099734 You're receiving this email because of your account on salsa.debian.org. -------------- next part -------------- An HTML attachment was scrubbed... URL: From gitlab at salsa.debian.org Sat Nov 1 08:11:07 2025 From: gitlab at salsa.debian.org (Marc Haber (@zugschlus)) Date: Sat, 01 Nov 2025 08:11:07 +0000 Subject: [Pkg-shadow-devel] [Git][debian/adduser][feature-refactor-existing] 8 commits: refactor existing_*_ok Message-ID: <6905c09b4c9cf_13a76d855ac505849@godard.mail> Marc Haber pushed to branch feature-refactor-existing at Debian / adduser Commits: efa21b2b by Matt Barry at 2025-11-01T09:10:42+01:00 refactor existing_*_ok replace with new existing_(user|group)_status, which return a bitmask value corresponding to these constants: EXISTING_NOT_FOUND EXISTING_FOUND EXISTING_SYSTEM EXISTING_ID_MISMATCH (and EXISTING_LOCKED, which is unused in this branch) - - - - - b0b64e33 by Marc Haber at 2025-11-01T09:10:42+01:00 more instrumentation output for system_status.t Git-Dch: ignore - - - - - 71830745 by Marc Haber at 2025-11-01T09:10:42+01:00 more instrumentation to identify tests Git-Dch: ignore - - - - - 344c513b by Marc Haber at 2025-11-01T09:10:42+01:00 adap test9 for new message output Git-Dch: ignore - - - - - 8bdbca34 by Marc Haber at 2025-11-01T09:10:42+01:00 adapt test to #109934 (EXISTING_HAS_PASSWORD) Git-Dch: ignore - - - - - 1187fa79 by Marc Haber at 2025-11-01T09:10:42+01:00 document a new error case (#1099734, EXISTING_HAS_PASSWORD) Git-Dch: ignore - - - - - 8f24be4f by Marc Haber at 2025-11-01T09:10:42+01:00 implement EXISTING_HAS_PASSWORD Git-Dch: ignore - - - - - fca13c5b by Marc Haber at 2025-11-01T09:10:42+01:00 improve documentation for check_user_group Git-Dch: ignore - - - - - 6 changed files: - AdduserCommon.pm - adduser - debian/tests/f/adduser_system.t - debian/tests/f/system_status.t - doc/adduser.8 - testsuite/test09.pl Changes: ===================================== AdduserCommon.pm ===================================== @@ -94,6 +94,16 @@ use constant { def_min_regex => qr(^[^-+~:,\s/][^:,\s/]*$)aa, }; +# constants used in existing_*_status +use constant { + EXISTING_NOT_FOUND => 0, + EXISTING_FOUND => 1, + EXISTING_SYSTEM => 2, + EXISTING_ID_MISMATCH => 4, + EXISTING_LOCKED => 8, + EXISTING_HAS_PASSWORD => 16, +}; + @EXPORT = ( 'get_group_members', 'read_config', @@ -122,6 +132,14 @@ use constant { 'def_sys_name_regex', 'def_ieee_name_regex', 'def_min_regex', + 'EXISTING_NOT_FOUND', + 'EXISTING_FOUND', + 'EXISTING_SYSTEM', + 'EXISTING_ID_MISMATCH', + 'EXISTING_LOCKED', + 'EXISTING_HAS_PASSWORD', + 'existing_user_status', + 'existing_group_status', ); sub sanitize_string { @@ -566,6 +584,67 @@ END { release_lock(1); } +# existing_user_status: check if there is already a user present +# on the system which satisfies the requirements +# parameter: +# new_name: the name of the user to check +# new_uid : the UID of the user +# return value: +# bitwise combination of these constants: +# EXISTING_NOT_FOUND => 0 +# EXISTING_FOUND => 1 +# EXISTING_SYSTEM => 2 +# EXISTING_ID_MISMATCH => 4 +# EXISTING_LOCKED => 8 +# EXISTING_HAS_PASSWORD => 16 +# e.g. if the requested account name exists as a locked system user, +# return 8|2|1 == 11 +sub existing_user_status { + my ($config, $new_name,$new_uid) = @_; + my ($dummy1,$pw,$uid); + my $ret = EXISTING_NOT_FOUND; + log_trace( "existing_user_status called with new_name %s, new_uid %s, first_system_uid %s, last_system_uid %s", $new_name, $new_uid, $config->{"first_system_uid"}, $config->{"last_system_uid"} ); + if (($dummy1,$pw,$uid) = egetpwnam($new_name)) { + # user with the name exists + log_trace( "egetpwnam(%s) returns %s, %s, %s", $new_name, $dummy1, $pw, $uid ); + $ret |= EXISTING_FOUND; + $ret |= EXISTING_ID_MISMATCH if (defined($new_uid) && $uid != $new_uid); + $ret |= EXISTING_SYSTEM if + (($uid >= $config->{"first_system_uid"}) && ($uid <= $config->{"last_system_uid"})); + $ret |= EXISTING_HAS_PASSWORD if + (defined $pw && $pw ne '' && $pw ne '!' && $pw !~ /^\*/); + $ret |= EXISTING_LOCKED if (substr($pw,0,1) eq "!"); # TODO: also check expiry? + } + log_trace( "existing_user_status returning %d", $ret ); + return $ret; +} + +# existing_group_status: check if there is already a group which satisfies the requirements +# parameter: +# new_name: the name of the group +# new_gid : the GID of the group +# return value: +# bitwise combination of these constants: +# EXISTING_NOT_FOUND => 0 +# EXISTING_FOUND => 1 +# EXISTING_SYSTEM => 2 +# EXISTING_ID_MISMATCH => 4 +sub existing_group_status { + my ($config, $new_name,$new_gid) = @_; + my ($dummy1,$dummy2,$gid); + my $ret = EXISTING_NOT_FOUND; + log_trace( "existing_group_status called with new_name %s, new_gid %s", $new_name, $new_gid ); + if (($dummy1,$dummy2,$gid) = egetgrnam($new_name)) { + # group with the name exists + $ret |= EXISTING_FOUND; + $ret |= EXISTING_ID_MISMATCH if (defined($new_gid) && $gid != $new_gid); + $ret |= EXISTING_SYSTEM if + (($gid >= $config->{"first_system_gid"} && $gid <= $config->{"last_system_gid"})); + } + log_trace( "existing_group_status returning %d", $ret ); + return $ret; +} + 1; # Local Variables: ===================================== adduser ===================================== @@ -88,14 +88,6 @@ BEGIN { } } -use constant { - EXISTING_NOT_FOUND => 0, - EXISTING_FOUND => 1, - EXISTING_SYSTEM => 2, - EXISTING_ID_MISMATCH => 4, - EXISTING_LOCKED => 8, -}; - my $yesexpr = langinfo(YESEXPR()); my $charset = langinfo($codeset); if ($encode_loaded) { @@ -103,7 +95,7 @@ if ($encode_loaded) { binmode(STDERR, ":encoding($charset)"); } -my %config; # configuration hash +my %config = (); my $nogroup_id = egetgrnam("nogroup") || 65534; $0 =~ s+.*/++; @@ -334,6 +326,15 @@ if ($found_group_opt) { } } +# $new_firstuid = $new_firstuid || $config{"first_uid"} || 1000; +# $new_lastuid = $new_lastuid || $config{"last_uid"} || 59999; +# $new_firstgid = $new_firstgid || $config{"first_gid"} || 1000; +# $new_lastgid = $new_lastgid || $config{"last_gid"} || 59999; +# $new_firstuid = $new_firstuid || $config{"first_uid"} || 1000; +# $new_lastuid = $new_lastuid || $config{"last_uid"} || 59999; +# $new_firstgid = $new_firstgid || $config{"first_gid"} || 1000; +# $new_lastgid = $new_lastgid || $config{"last_gid"} || 59999; + # read the uid and gid pool if ($config{"uid_pool"}) { @@ -387,7 +388,7 @@ if( defined $new_firstuid ) { } if( defined $new_lastuid ) { - log_trace("sanitize new_lastgud"); + log_trace("sanitize new_lastuid"); $new_lastuid = sanitize_string($new_lastuid, numberre); } @@ -439,23 +440,26 @@ $SIG{'INT'} = $SIG{'QUIT'} = $SIG{'HUP'} = 'handler'; if ($action eq "addsysgroup") { acquire_lock(); + + log_trace( "addsysuser %s, uid %s", $new_name, $new_uid ); # Check if requested group already exists and we can exit safely - my $asgret = existing_group_status($new_name, $gid_option); + my $asgret = existing_group_status(\%config, $new_name, $gid_option); log_trace( "existing_group_status( %s, %s ) returns %s", $new_name, $gid_option, $asgret ); + if ($asgret & EXISTING_FOUND) { + # a group with this name already exists; it's a problem when it's not a system group + if ( ( $asgret & EXISTING_SYSTEM ) == 0 ) { + log_fatal( mtx("The group `%s' already exists, but is not a system group. Exiting."), $new_name ); + exit( RET_WRONG_OBJECT_PROPERTIES ); + } + } if ($asgret & EXISTING_ID_MISMATCH) { log_err( mtx("The group `%s' already exists, but has a different GID. Exiting."), $new_name ); exit( RET_WRONG_OBJECT_PROPERTIES ); } if ($asgret & EXISTING_FOUND) { - log_trace( "existing_found" ); - if ($asgret & (EXISTING_SYSTEM)) { - log_info( mtx("The group `%s' already exists as a system group."), $new_name ); - exit( RET_OK ); - } else { - log_err( mtx("The group `%s' already exists and is not a system group. Exiting."), $new_name ); - exit( RET_WRONG_OBJECT_PROPERTIES ); - } + log_info( mtx("The system group `%s' already exists. Exiting.\n"), $new_name ); + exit( RET_OK ); } if (defined($gid_option) && defined(getgrgid($gid_option))) { log_fatal( mtx("The GID `%s' is already in use."), $gid_option ); @@ -567,11 +571,14 @@ if ($action eq 'addusertogroup') { if ($action eq "addsysuser") { acquire_lock(); - my $ret = existing_user_status($new_name, $new_uid); - if (($ret & EXISTING_FOUND) && !($ret & EXISTING_SYSTEM)) { + log_trace( "addsysuser %s, uid %s", $new_name, $new_uid ); + my $ret = existing_user_status(\%config, $new_name, $new_uid); + if ($ret & (EXISTING_FOUND)) { # a user with this name already exists; it's a problem when it's not a system user - log_fatal( mtx("The user `%s' already exists, but is not a system user. Exiting."), $new_name ); - exit( RET_WRONG_OBJECT_PROPERTIES ); + if ( ($ret & EXISTING_SYSTEM) == 0 ) { + log_fatal( mtx("The user `%s' already exists, but is not a system user. Exiting."), $new_name ); + exit( RET_WRONG_OBJECT_PROPERTIES ); + } } if ($ret & EXISTING_ID_MISMATCH) { log_fatal( mtx("The user `%s' already exists with a different UID. Exiting."), $new_name ); @@ -1140,96 +1147,43 @@ sub mktree { return 1; } -# existing_user_status: check if there is already a user present -# on the system which satisfies the requirements -# parameter: -# new_name: the name of the user to check -# new_uid : the UID of the user -# return value: -# bitwise combination of these constants: -# EXISTING_NOT_FOUND => 0 -# EXISTING_FOUND => 1 -# EXISTING_SYSTEM => 2 -# EXISTING_ID_MISMATCH => 4 -# EXISTING_LOCKED => 8 -# e.g. if the requested account name exists as a locked system user, -# return 8|2|1 == 11 -sub existing_user_status { - my ($new_name,$new_uid) = @_; - my ($pw,$uid); - my $ret = EXISTING_NOT_FOUND; - log_trace( "existing_user_status called with new_name %s, new_uid %s", $new_name, $new_uid ); - if ((undef,$pw,$uid) = egetpwnam($new_name)) { - log_trace("egetpwnam %s returned successfully, uid = %s", $new_name, $uid); - $ret |= EXISTING_FOUND; - $ret |= EXISTING_ID_MISMATCH if (defined($new_uid) && $uid != $new_uid); - $ret |= EXISTING_SYSTEM if - ($uid >= $config{"first_system_uid"} && $uid <= $config{"last_system_uid"}); - } elsif ($new_uid && getpwuid($new_uid)) { - $ret |= EXISTING_ID_MISMATCH; - } - log_trace( "existing_user_status( %s, %s ) returns %s", $new_name, $new_uid, $ret ); - return $ret; -} - -# existing_group_status: check if there is already a group which satisfies the requirements -# parameter: -# new_name: the name of the group -# new_gid : the GID of the group -# return value: -# bitwise combination of these constants: -# EXISTING_NOT_FOUND => 0 -# EXISTING_FOUND => 1 -# EXISTING_SYSTEM => 2 -# EXISTING_ID_MISMATCH => 4 -sub existing_group_status { - my ($new_name,$new_gid) = @_; - my $gid; - my $ret = EXISTING_NOT_FOUND; - log_trace( "existing_group_status called with new_name %s, new_gid %s", $new_name, $new_gid ); - if ((undef,undef,$gid) = egetgrnam($new_name)) { - log_trace("egetgrnam %s returned successfully, gid = %s", $new_name, $gid); - $ret |= EXISTING_FOUND; - $ret |= EXISTING_ID_MISMATCH if (defined($new_gid) && $gid != $new_gid); - $ret |= EXISTING_SYSTEM if - ($gid >= $config{"first_system_gid"} && $gid <= $config{"last_system_gid"}); - } elsif ($new_gid && getgrgid($new_gid)) { - $ret |= EXISTING_ID_MISMATCH; - } - log_trace( "existing_group_status( %s, %s ) returns %s", $new_name, $new_gid, $ret ); - return $ret; -} - -# check_user_group: ??? +# check_user_group: Do checks regarding user, group, gid and group +# requirement that are basically the same for normal users and +# system users. Factored out to avoid code duplication. # parameters: # system: 0 if the user is not a system user, 1 otherwise # return values: -# +# if the function returns, all requirements are met. otherwise +# it exits() from the program with an appropriate exit code # todo: not sure whether global variables apply fine here. +# global variables used: +# $make_group_also +# $new_name +# $new_uid +# $ingroup_name +# $gid_option sub check_user_group { my ($system) = @_; log_debug( "check_user_group %s called, make_group_also %s", $system, $make_group_also ); - - my $ustat = existing_user_status($new_name, $new_uid); - if ($system) { - if (($ustat & EXISTING_FOUND) && !($ustat & EXISTING_SYSTEM)) { - log_fatal( mtx("The user `%s' already exists, and is not a system user."), $new_name); - exit( RET_WRONG_OBJECT_PROPERTIES ); + if( !$system || !existing_user_status(\%config, $new_name, $new_uid) ) { + if( defined egetpwnam($new_name) ) { + if( $system ) { + log_fatal( mtx("The user `%s' already exists, and is not a system user."), $new_name); + exit( RET_WRONG_OBJECT_PROPERTIES ); + } else { + log_fatal( mtx("The user `%s' already exists."), $new_name); + exit( RET_OBJECT_EXISTS ); + } } - # if ($new_uid && !($ustat & EXISTING_SYSTEM)) { - # log_fatal( mtx("The uid `%s' is invalid for system users."), $new_name); - # exit( RET_OBJECT_EXISTS ); - # } - } else { - if ($ustat & EXISTING_FOUND) { - log_fatal( mtx("The user `%s' already exists."), $new_name); - exit( RET_OBJECT_EXISTS ); + if (defined($new_uid) && getpwuid($new_uid)) { + log_fatal( mtx("The UID %d is already in use."), $new_uid); + exit( RET_ID_IN_USE ); } } if ($make_group_also) { log_trace( "make_group_also 1, new_name %s, new_uid %s", $new_name, $new_uid ); - if( !$system || !existing_group_status($new_name, $new_uid) ) { + if( !$system || !existing_group_status(\%config, $new_name, $new_uid) ) { if (defined egetgrnam($new_name)) { log_fatal( mtx("The group `%s' already exists."),$new_name ); exit( RET_OBJECT_EXISTS ); ===================================== debian/tests/f/adduser_system.t ===================================== @@ -12,6 +12,15 @@ use warnings; use AdduserTestsCommon; +# how do I use a module from the package in question? +#use AdduserRetvalues; + +use constant RET_OK => 0; +use constant RET_OBJECT_EXISTS => 11; +use constant RET_OBJECT_DOES_NOT_EXIST => 12; +use constant RET_WRONG_OBJECT_PROPERTIES => 13; +use constant RET_NO_PRIMARY_GID => 23; + END { remove_tree('/home/aust'); @@ -184,6 +193,7 @@ assert_user_exists('aust'); assert_user_is_system('aust'); system('echo "aust:*" | chpasswd --encrypted'); +ok(1, "set passwd to *"); assert_command_success( '/usr/sbin/adduser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -195,7 +205,8 @@ assert_user_exists('aust'); assert_user_is_system('aust'); system('echo "aust:!foobar" | chpasswd --encrypted'); -assert_command_success( +# with #1099734 fixed, this should fail +assert_command_result_silent(RET_WRONG_OBJECT_PROPERTIES, '/usr/sbin/adduser', '--stdoutmsglevel=error', '--stderrmsglevel=error', '--system', @@ -206,6 +217,7 @@ assert_user_exists('aust'); assert_user_is_system('aust'); system('echo "aust:*foobar" | chpasswd --encrypted'); +ok(1, "set passwd to *foobar"); assert_command_success( '/usr/sbin/adduser', '--stdoutmsglevel=error', '--stderrmsglevel=error', ===================================== debian/tests/f/system_status.t ===================================== @@ -56,6 +56,7 @@ my $name = "sys-stat-t"; # number existing before operation result existing after # 11 nothing create system success system +ok(1, "sys-stat-t 11"); assert_user_does_not_exist($name); assert_command_success( @@ -71,6 +72,7 @@ assert_user_is_system($name); # 12 system create system success system # above: assert_user_exists($name); # above: assert_user_is_system($name); +ok(1, "sys-stat-t 12"); assert_command_success( '/usr/sbin/adduser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -84,6 +86,7 @@ assert_user_is_system($name); # 13 system delete system success nothing # above: assert_user_exists($name); # above: assert_user_is_system($name); +ok(1, "sys-stat-t 13"); assert_command_success( '/usr/sbin/deluser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -95,6 +98,7 @@ assert_user_does_not_exist($name); # number existing before operation result existing after # 14 nothing delete system obj_not_ex nothing # above: assert_user_does_not_exist($name); +ok(1, "sys-stat-t 14"); assert_command_success( '/usr/sbin/deluser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -106,6 +110,7 @@ assert_user_does_not_exist($name); # number existing before operation result existing after # 15 nothing delete nonsys obj_not_ex nothing # above: assert_user_does_not_exist($name); +ok(1, "sys-stat-t 15"); assert_command_result_silent(RET_OBJECT_DOES_NOT_EXIST, '/usr/sbin/deluser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -117,6 +122,7 @@ assert_user_does_not_exist($name); # 21 nothing create system success system # above: assert_user_does_not_exist($name); +ok(1, "sys-stat-t 21"); assert_command_success( '/usr/sbin/adduser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -129,6 +135,7 @@ assert_user_is_system($name); # number existing before operation result existing after # 22 system create nonsys obj_exists system # above: assert_user_is_system($name); +ok(1, "sys-stat-t 22"); assert_command_result_silent(RET_OBJECT_EXISTS, '/usr/sbin/adduser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -145,6 +152,7 @@ assert_user_is_system($name); # in adduser 3.145, this succeeds! # above: assert_user_is_system($name); #assert_command_result_silent(RET_WRONG_OBJECT_PROPERTIES, +ok(1, "sys-stat-t 23"); assert_command_success( '/usr/sbin/deluser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -164,6 +172,7 @@ assert_user_is_system($name); # number existing before operation result existing after # 24 system delete system success nothing # above: assert_user_is_system($name); +ok(1, "sys-stat-t 24"); assert_command_success( '/usr/sbin/deluser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -175,6 +184,7 @@ assert_user_does_not_exist($name); # number existing before operation result existing after # 31 nothing create nonsys success nonsys # above: assert_user__does_not_exist($name); +ok(1, "sys-stat-t 31"); assert_command_success( '/usr/sbin/adduser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -190,6 +200,7 @@ assert_user_is_non_system($name); # 32 nonsys create nonsys obj_exists nonsys # above: assert_user_exists($name); # above: assert_user_is_non_system($name); +ok(1, "sys-stat-t 32"); assert_command_result_silent(RET_OBJECT_EXISTS, '/usr/sbin/adduser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -205,6 +216,7 @@ assert_user_is_non_system($name); # 33 nonsys delete sys wrong_prop nonsys # above: assert_user_exists($name); # above: assert_user_is_non_system($name); +ok(1, "sys-stat-t 33"); assert_command_result_silent(RET_WRONG_OBJECT_PROPERTIES, '/usr/sbin/deluser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -218,6 +230,7 @@ assert_user_is_non_system($name); # 34 nonsys create sys wrong_prop nonsys # above: assert_user_exists($name); # above: assert_user_is_non_system($name); +ok(1, "sys-stat-t 34a"); assert_command_result_silent(RET_WRONG_OBJECT_PROPERTIES, '/usr/sbin/adduser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -231,6 +244,7 @@ assert_user_is_non_system($name); # 35 nonsys delete nonsys success nothing # above: assert_user_exists($name); # above: assert_user_is_non_system($name); +ok(1, "sys-stat-t 35"); assert_command_success( '/usr/sbin/deluser', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -243,6 +257,7 @@ assert_user_does_not_exist($name); # number existing before operation result existing after # 11 nothing create system success system +ok(1, "sys-stat-t 11"); assert_group_does_not_exist($name); assert_command_success( @@ -258,6 +273,7 @@ assert_group_is_system($name); # 12 system create system success system # above: assert_group_exists($name); # above: assert_group_is_system($name); +ok(1, "sys-stat-t 12"); assert_command_success( '/usr/sbin/addgroup', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -271,6 +287,7 @@ assert_group_is_system($name); # 13 system delete system success nothing # above: assert_group_exists($name); # above: assert_group_is_system($name); +ok(1, "sys-stat-t 13"); assert_command_success( '/usr/sbin/delgroup', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -282,6 +299,7 @@ assert_group_does_not_exist($name); # number existing before operation result existing after # 14 nothing delete system obj_not_ex nothing # above: assert_group_does_not_exist($name); +ok(1, "sys-stat-t 14"); assert_command_success( '/usr/sbin/delgroup', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -293,6 +311,7 @@ assert_group_does_not_exist($name); # number existing before operation result existing after # 15 nothing delete nonsys obj_not_ex nothing # above: assert_group_does_not_exist($name); +ok(1, "sys-stat-t 15"); assert_command_result_silent(RET_OBJECT_DOES_NOT_EXIST, '/usr/sbin/delgroup', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -304,6 +323,7 @@ assert_group_does_not_exist($name); # 21 nothing create system success system # above: assert_group_does_not_exist($name); +ok(1, "sys-stat-t 21"); assert_command_success( '/usr/sbin/addgroup', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -316,6 +336,7 @@ assert_group_is_system($name); # number existing before operation result existing after # 22 system create nonsys obj_exists system # above: assert_group_is_system($name); +ok(1, "sys-stat-t 22"); assert_command_result_silent(RET_OBJECT_EXISTS, '/usr/sbin/addgroup', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -332,6 +353,7 @@ assert_group_is_system($name); # in addgroup 3.145, this succeeds! # above: assert_group_is_system($name); #assert_command_result_silent(RET_WRONG_OBJECT_PROPERTIES, +ok(1, "sys-stat-t 23"); assert_command_success( '/usr/sbin/delgroup', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -351,6 +373,7 @@ assert_group_is_system($name); # number existing before operation result existing after # 24 system delete system success nothing # above: assert_group_is_system($name); +ok(1, "sys-stat-t 24"); assert_command_success( '/usr/sbin/delgroup', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -362,6 +385,7 @@ assert_group_does_not_exist($name); # number existing before operation result existing after # 31 nothing create nonsys success nonsys # above: assert_group__does_not_exist($name); +ok(1, "sys-stat-t 31"); assert_command_success( '/usr/sbin/addgroup', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -377,6 +401,7 @@ assert_group_is_non_system($name); # 32 nonsys create nonsys obj_exists nonsys # above: assert_group_exists($name); # above: assert_group_is_non_system($name); +ok(1, "sys-stat-t 32"); assert_command_result_silent(RET_OBJECT_EXISTS, '/usr/sbin/addgroup', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -392,6 +417,7 @@ assert_group_is_non_system($name); # 33 nonsys delete sys wrong_prop nonsys # above: assert_group_exists($name); # above: assert_group_is_non_system($name); +ok(1, "sys-stat-t 33"); assert_command_result_silent(RET_WRONG_OBJECT_PROPERTIES, '/usr/sbin/delgroup', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -405,6 +431,7 @@ assert_group_is_non_system($name); # 34 nonsys create sys wrong_prop nonsys # above: assert_group_exists($name); # above: assert_group_is_non_system($name); +ok(1, "sys-stat-t 34b"); assert_command_result_silent(RET_WRONG_OBJECT_PROPERTIES, '/usr/sbin/addgroup', '--stdoutmsglevel=error', '--stderrmsglevel=error', @@ -418,6 +445,7 @@ assert_group_is_non_system($name); # 35 nonsys delete nonsys success nothing # above: assert_group_exists($name); # above: assert_group_is_non_system($name); +ok(1, "sys-stat-t 35"); assert_command_success( '/usr/sbin/delgroup', '--stdoutmsglevel=error', '--stderrmsglevel=error', ===================================== doc/adduser.8 ===================================== @@ -259,6 +259,8 @@ Unless a shell is explicitly set with the \fB\-\-shell\fP option, the new system user will have the shell set to \fI/usr/sbin/nologin\fP. \fBadduser \-\-system\fP does not set a password for the new account. +It is an error if \fBadduser \-\-system\fP is called +for an account that has a password. Skeletal configuration files are not copied. .PP Other options will behave as for the creation of a regular user. ===================================== testsuite/test09.pl ===================================== @@ -56,7 +56,7 @@ if ($error ne 13) { print "failed\n $cmd returned an errorcode != 13 ($error)\n"; exit $error; } -if ($output !~ /^err: The group `addusertest\d+' already exists and is not a system group. Exiting.$/ ) { +if ($output !~ /^fatal: The group `addusertest\d+' already exists, but is not a system group. Exiting.$/ ) { print "failed\n $cmd returned unexpected output ($output)\n"; exit 1; } View it on GitLab: https://salsa.debian.org/debian/adduser/-/compare/b7c9d3a138f37a0f174968ebb3600f6c5e0de454...fca13c5bd5d933e9a5c668077c83b9aec0264d44 -- View it on GitLab: https://salsa.debian.org/debian/adduser/-/compare/b7c9d3a138f37a0f174968ebb3600f6c5e0de454...fca13c5bd5d933e9a5c668077c83b9aec0264d44 You're receiving this email because of your account on salsa.debian.org. -------------- next part -------------- An HTML attachment was scrubbed... URL: From gitlab at salsa.debian.org Sat Nov 1 08:24:57 2025 From: gitlab at salsa.debian.org (Marc Haber (@zugschlus)) Date: Sat, 01 Nov 2025 08:24:57 +0000 Subject: [Pkg-shadow-devel] [Git][debian/adduser][feature-refactor-existing] 5 commits: adapt test9 for new message output Message-ID: <6905c3d97f499_13a76d2908745132a7@godard.mail> Marc Haber pushed to branch feature-refactor-existing at Debian / adduser Commits: d92eb8e6 by Marc Haber at 2025-11-01T09:19:57+01:00 adapt test9 for new message output Git-Dch: ignore - - - - - 49118ec3 by Marc Haber at 2025-11-01T09:19:59+01:00 adapt test to #109934 (EXISTING_HAS_PASSWORD) Git-Dch: ignore - - - - - 1679e780 by Marc Haber at 2025-11-01T09:19:59+01:00 document a new error case (#1099734, EXISTING_HAS_PASSWORD) Git-Dch: ignore - - - - - 28c5258d by Marc Haber at 2025-11-01T09:19:59+01:00 implement EXISTING_HAS_PASSWORD Git-Dch: ignore - - - - - d5078067 by Marc Haber at 2025-11-01T09:19:59+01:00 improve documentation for check_user_group Git-Dch: ignore - - - - - 5 changed files: - AdduserCommon.pm - adduser - debian/tests/f/adduser_system.t - doc/adduser.8 - testsuite/test09.pl Changes: ===================================== AdduserCommon.pm ===================================== @@ -101,6 +101,7 @@ use constant { EXISTING_SYSTEM => 2, EXISTING_ID_MISMATCH => 4, EXISTING_LOCKED => 8, + EXISTING_HAS_PASSWORD => 16, }; @EXPORT = ( @@ -136,6 +137,7 @@ use constant { 'EXISTING_SYSTEM', 'EXISTING_ID_MISMATCH', 'EXISTING_LOCKED', + 'EXISTING_HAS_PASSWORD', 'existing_user_status', 'existing_group_status', ); @@ -594,6 +596,7 @@ END { # EXISTING_SYSTEM => 2 # EXISTING_ID_MISMATCH => 4 # EXISTING_LOCKED => 8 +# EXISTING_HAS_PASSWORD => 16 # e.g. if the requested account name exists as a locked system user, # return 8|2|1 == 11 sub existing_user_status { @@ -602,11 +605,14 @@ sub existing_user_status { my $ret = EXISTING_NOT_FOUND; log_trace( "existing_user_status called with new_name %s, new_uid %s, first_system_uid %s, last_system_uid %s", $new_name, $new_uid, $config->{"first_system_uid"}, $config->{"last_system_uid"} ); if (($dummy1,$pw,$uid) = egetpwnam($new_name)) { + # user with the name exists log_trace( "egetpwnam(%s) returns %s, %s, %s", $new_name, $dummy1, $pw, $uid ); $ret |= EXISTING_FOUND; $ret |= EXISTING_ID_MISMATCH if (defined($new_uid) && $uid != $new_uid); $ret |= EXISTING_SYSTEM if (($uid >= $config->{"first_system_uid"}) && ($uid <= $config->{"last_system_uid"})); + $ret |= EXISTING_HAS_PASSWORD if + (defined $pw && $pw ne '' && $pw ne '!' && $pw !~ /^\*/); $ret |= EXISTING_LOCKED if (substr($pw,0,1) eq "!"); # TODO: also check expiry? } log_trace( "existing_user_status returning %d", $ret ); @@ -629,6 +635,7 @@ sub existing_group_status { my $ret = EXISTING_NOT_FOUND; log_trace( "existing_group_status called with new_name %s, new_gid %s", $new_name, $new_gid ); if (($dummy1,$dummy2,$gid) = egetgrnam($new_name)) { + # group with the name exists $ret |= EXISTING_FOUND; $ret |= EXISTING_ID_MISMATCH if (defined($new_gid) && $gid != $new_gid); $ret |= EXISTING_SYSTEM if ===================================== adduser ===================================== @@ -1147,12 +1147,21 @@ sub mktree { return 1; } -# check_user_group: ??? +# check_user_group: Do checks regarding user, group, gid and group +# requirement that are basically the same for normal users and +# system users. Factored out to avoid code duplication. # parameters: # system: 0 if the user is not a system user, 1 otherwise # return values: -# +# if the function returns, all requirements are met. otherwise +# it exits() from the program with an appropriate exit code # todo: not sure whether global variables apply fine here. +# global variables used: +# $make_group_also +# $new_name +# $new_uid +# $ingroup_name +# $gid_option sub check_user_group { my ($system) = @_; log_debug( "check_user_group %s called, make_group_also %s", $system, $make_group_also ); ===================================== debian/tests/f/adduser_system.t ===================================== @@ -12,6 +12,15 @@ use warnings; use AdduserTestsCommon; +# how do I use a module from the package in question? +#use AdduserRetvalues; + +use constant RET_OK => 0; +use constant RET_OBJECT_EXISTS => 11; +use constant RET_OBJECT_DOES_NOT_EXIST => 12; +use constant RET_WRONG_OBJECT_PROPERTIES => 13; +use constant RET_NO_PRIMARY_GID => 23; + END { remove_tree('/home/aust'); @@ -196,7 +205,8 @@ assert_user_exists('aust'); assert_user_is_system('aust'); system('echo "aust:!foobar" | chpasswd --encrypted'); -ok(1, "set passwd to !foobar"); +# with #1099734 fixed, this should fail +#assert_command_result_silent(RET_WRONG_OBJECT_PROPERTIES, assert_command_success( '/usr/sbin/adduser', '--stdoutmsglevel=error', '--stderrmsglevel=error', ===================================== doc/adduser.8 ===================================== @@ -259,6 +259,8 @@ Unless a shell is explicitly set with the \fB\-\-shell\fP option, the new system user will have the shell set to \fI/usr/sbin/nologin\fP. \fBadduser \-\-system\fP does not set a password for the new account. +It is an error if \fBadduser \-\-system\fP is called +for an account that has a password. Skeletal configuration files are not copied. .PP Other options will behave as for the creation of a regular user. ===================================== testsuite/test09.pl ===================================== @@ -56,7 +56,7 @@ if ($error ne 13) { print "failed\n $cmd returned an errorcode != 13 ($error)\n"; exit $error; } -if ($output !~ /^err: The group `addusertest\d+' already exists and is not a system group. Exiting.$/ ) { +if ($output !~ /^fatal: The group `addusertest\d+' already exists, but is not a system group. Exiting.$/ ) { print "failed\n $cmd returned unexpected output ($output)\n"; exit 1; } View it on GitLab: https://salsa.debian.org/debian/adduser/-/compare/fca13c5bd5d933e9a5c668077c83b9aec0264d44...d5078067807af978f4e67286ac4e31dc52dfddaa -- View it on GitLab: https://salsa.debian.org/debian/adduser/-/compare/fca13c5bd5d933e9a5c668077c83b9aec0264d44...d5078067807af978f4e67286ac4e31dc52dfddaa You're receiving this email because of your account on salsa.debian.org. -------------- next part -------------- An HTML attachment was scrubbed... URL: