Index: slimserver.pl =================================================================== --- slimserver.pl (revision 12724) +++ slimserver.pl (working copy) @@ -869,75 +869,105 @@ return; } + # If we're not root and need to change user and group then die with a + # suitable message, else there's nothing more to do, so return. + if ($> != 0) { + + if (defined($user) || defined($group)) { + + my $uname = getpwuid($>); + print STDERR "Current user is $uname\n"; + print STDERR "Must run as root to change effective user or group.\n"; + die "Aborting"; + + } else { + + return; + + } + + } + + my ($uid, $pgid, @sgids, $gid); + # Don't allow the server to be started as root. # MySQL can't be run as root, and it's generally a bad idea anyways. - # - # See if there's a slimserver user we can switch to. - if ($> == 0 && !$user) { + # Try starting as 'slimserver' instead. + if (!defined($user)) { + $user = 'slimserver'; + print STDERR "Slimserver must not be run as root! Trying user $user instead.\n"; + } - my $testUser = 'slimserver'; - my $uid = getpwnam($testUser); - if ($> == 0 && (!defined $uid || $uid == 0)) { + # Get the uid and primary group id for the $user. + ($uid, $pgid) = (getpwnam($user))[2,3]; - # Don't allow the server to be started as root. - # MySQL can't be run as root, and it's generally a bad idea anyways. - print "* Error: SlimServer must not be run as root! Exiting! *\n"; - exit; + if (!defined ($uid)) { + die "User $user not found.\n"; + } - } else { - $user = $testUser; - } + # Get the supplementary groups to which $user belongs + + setgrent(); + + while (my @grp = getgrent()) { + if ($grp[3] =~ m/\b$user\b/){ push @sgids, $grp[2] } } - # Do we want to change the effective user or group? - if (defined($user) || defined($group)) { + endgrent(); - # Can only change effective UID/GID if root - if ($> != 0) { - my $uname = getpwuid($>); - print STDERR "Current user is $uname\n"; - print STDERR "Must run as root to change effective user or group.\n"; - die "Aborting"; + # If a group was specified, get the gid of it and add it to the + # list of supplementary groups. + if (defined($group)) { + $gid = getgrnam($group); + + if (!defined $gid) { + die "Group $group not found.\n"; + } else { + push @sgids, $gid; } + } - # Change effective group ID if necessary - # Need to do this while still root, so do group first - if (defined($group)) { + # Check that we're definately not trying to start as root, e.g. if + # we were passed '--user root' or any other used with uid 0. + if ($uid == 0) { + print STDERR "SlimServer must not be run as root! Exiting!\n"; + die "Aborting"; + } - my $gid = getgrnam($group); - if (!defined $gid) { - die "Group $group not found.\n"; - } + # Change effective group. Need to do this while still root, so do group first - $) = $gid; + # $) is a space separated list that begins with the effective gid then lists + # any supplementary group IDs, so compare against that. On some systems + # no supplementary group IDs are present at system startup or at all. - # $) is a space separated list that begins with the effective gid then lists - # any supplementary group IDs, so compare against that. On some systems - # no supplementary group IDs are present at system startup or at all. - if ( $) !~ /^$gid\b/) { - die "Unable to set effective group(s) to $group ($gid) is: $): $!\n"; - } - } + # We need to pass $pgid twice because setgroups only gets called if there's + # more than one value. For example, if we did: + # $) = "1234" + # then the effective primary group would become 1234, but we'd retain any + # previously set supplementary groups. To become a member of just 1234, the + # correct way is to do: + # $) = "1234 1234" - # Change effective user ID if necessary - if (defined($user)) { + undef $!; + $) = "$pgid $pgid " . join (" ", @sgids); - my $uid = getpwnam($user); + if ( $! ) { + die "Unable to set effective group(s) to $group ($gid) is: $): $!\n"; + } - if (!defined ($uid)) { - die "User $user not found.\n"; - } + # Finally, change effective user id. - $> = $uid; + undef $!; + $> = $uid; - if ($> != $uid) { - die "Unable to set effective user to $user, ($uid)!\n"; - } - } + if ( $! ) { + die "Unable to set effective user to $user, ($uid)!\n"; } + + $::d_server && msg("Running as:\nuid: $>\ngid: $)\n"); } sub checkDataSource {