Как узнать исходное имя пользователя, с которого был запущен процесс? - PullRequest
4 голосов
/ 14 марта 2010

Существует сценарий Perl, который должен запускаться от имени пользователя root, но мы должны убедиться, что пользователь, который запускает сценарий, не вошел в систему как пользователь 'foo', так как он будет удален во время выполнения сценария.

Итак, как я могу узнать, не пользователь, который мог несколько раз подать запрос с тех пор, как он вошел в систему, не выдавал себя за 'foo' в этой цепочке?

Я нашел интересный сценарий perl, который вызывал следующие два сценария оболочки, но я думаю, что он будет работать только на Solaris.

my $shell_parent = 
`ps -ef | grep -v grep | awk \'{print \$2\" \"\$3}\' | egrep \"^@_\" | awk \'{print \$2}'`;

my $parent_owner = 
`ps -ef | grep -v grep | awk \'{print \$1\" \"\$2}\' | grep @_ | awk \'{print \$1}\'`;

Это должно работать как на Linux, так и на Solaris, и я бы предпочел исключить повторные вызовы оболочки и сохранить все это в Perl.

Ответы [ 4 ]

1 голос
/ 15 марта 2010

Быстро и грязно и (только для UNIX):

my $user = (split /\s/,`who am i`)[0];

Команда who am i возвращает владельца TTY - то есть, кем вы были, когда вы вошли в систему.

Если вы хотите сделать это на чистом Perl:

use POSIX;
my $tty = POSIX::ttyname(1); # The tty we are running in
my $uid = (stat $tty)[4];    # The owner uid of that tty
my $user = getpwuid($uid);   # The user with that uid

Это вернет правильного пользователя, даже после нескольких su. Это обычно выводит из строя ваших (менее опытных) системных администраторов.

0 голосов
/ 13 марта 2013

Я распознал угловой случай при вызове сценариев из mc (по крайней мере, в нашем RHEL), в результате чего who am i ничего не выводит. Чтобы обойти это, я произвел следующую строку в bash:

REALUSERNAME=$(ps uhp `ps -AjH | grep \`ps -u $USER fh | awk '{ print $0; if(index($0, "ps -u $USER fh")) exit 0;}' | tac | awk '{if(!index($0, "\\\\\_")){print $1; exit 0;}}'\` | awk '{print $3}'` | awk '{print $1}')

По сути, это идет назад к выводу дерева ps -u $USER fh и затем обрезает верхний столбец имени пользователя.

Мысли, лучшие решения приветствуются: -)

0 голосов
/ 14 марта 2010

Может быть, это то, что вы хотите. Функция hasBeenUser читает таблицу процессов и затем следует цепочке процессов от текущего процесса до родительского процесса. Если какой-либо из процессов в пути имеет поле user или real user, равное рассматриваемому имени пользователя, функция возвращает ненулевое значение.

#! /usr/bin/perl

sub hasBeenUser($) {
        my ($username) = @_;

        my $procs = {};
        open(PS, "ps -e -o pid,ppid,user,ruser |") or die;
        while (defined(my $line = <PS>)) {
                next unless $line =~ m"^(\d+)\s+(\d+)\s+(\S+)\s+(\S+)\s+$";
                my ($pid, $ppid, $user, $ruser) = (int($1), int($2), $3, $4);
                $procs->{$pid} = [$pid, $ppid, $user, $ruser];
        }
        close(PS) or die;

        my $pid = $$;
        while (exists($procs->{$pid})) {
                my $proc = $procs->{$pid};
                delete $procs->{$pid}; # don't risk ending in an endless loop.
                warn "D: checking process $pid\n";
                if ($proc->[2] eq $username || $proc[3] eq $username) {
                        warn "E: process $pid was called by $username.\n";
                        return 1;
                }
                last if $pid < 2;
                $pid = $proc->[1];
        }
        return 0;
}

hasBeenUser("del"); # should return 0
hasBeenUser("root"); # should return nonzero
0 голосов
/ 14 марта 2010

Вот программа Perl, которая проверяет прямое изменение setuid:

#! /usr/bin/perl

sub callingUser() {
    my ($login, $pass, $uid, $gid) = getpwuid($<);
    return $login;
}

sub effectiveUser() {
    my ($login, $pass, $uid, $gid) = getpwuid($>);
    return $login;
}

printf("Real user name: %s\n", effectiveUser());
printf("Calling user name: %s\n", callingUser());

Но поскольку вы упомянули, что изменение setuid могло произойти в любое время раньше, вам, вероятно, придется проанализировать вывод ps: я бы сделал это с помощью следующей команды Эта команда использует только функции, определенные в POSIX , поэтому я надеюсь, что она переносима на все виды систем:

ps -e -o pid,ppid,user,ruser
...