fix: accountCreate --uid-auto: rare case where a free UID couldn't be found

This happened when a free UID was found, along with a corresponding GID,
but the corresponding GID for the ttyrec group of the account was not
available. Now this is checked directly in get_next_available_uid()
This commit is contained in:
Stéphane Lesimple 2021-07-13 11:42:28 +00:00 committed by Stéphane Lesimple
parent 6b4418e864
commit c0bebf23d4
2 changed files with 30 additions and 4 deletions

View file

@ -120,7 +120,7 @@ if (defined $uid) {
getgrgid($uid) and HEXIT('ERR_GID_COLLISION', msg => "This GID ($uid) is already taken");
}
elsif ($uidAuto) {
$fnret = OVH::Bastion::get_next_available_uid();
$fnret = OVH::Bastion::get_next_available_uid(available_gid => 1, available_gid_ttyrec => 1);
$fnret or HEXIT($fnret);
$uid = $fnret->value();
}

View file

@ -114,14 +114,40 @@ sub is_valid_uid {
sub get_next_available_uid {
my %params = @_;
# if true, also check for the availablility of the corresponding GID:
my $available_gid = $params{'available_gid'};
# if true, also check for the availability of the corresponding GID + the ttyrec offset:
my $available_gid_ttyrec = $params{'available_gid_ttyrec'};
my $higher = OVH::Bastion::config('accountUidMax')->value();
my $lower = OVH::Bastion::config('accountUidMin')->value();
my $next = $higher;
my $found = 0;
while (1) {
# find the first available UID, starting from the upper ID allowed and decrementing
while ($next >= $lower) {
last if not scalar(getpwuid($next));
$next--;
}
return R('OK', value => $next) if not scalar(getpwuid($next));
# did we get out of the loop because we found a candidate, or because we're out of bounds?
last if $next < $lower;
# if $available_gid, also check if the corresponding GID is available
# if $available_gid_ttyrec, also check if the corresponding GID + the ttyrec offset is available
if ( (!$available_gid || !scalar(getgrgid($next)))
&& (!$available_gid_ttyrec || !scalar(getgrgid($next + OVH::Bastion::config('ttyrecGroupIdOffset')->value))))
{
$found = 1;
last;
}
# if we're here, at least one of the $available_gid* check failed, so continue looking
$next--;
}
return R('OK', value => $next) if $found;
return R('ERR_UID_COLLISION', msg => "No available UID in the allowed range");
}