Изучаем Perl
975b8bba

Получение информации о паролях и группах


Информация о вашем пользовательском имени и идентификаторе, кото-рая имеется в системе UNIX, практически открыта. По сути дела, любая программа, которая не сочтет за труд заглянуть в файл /etc/passwd,

поможет вам увидеть почти все, кроме незашифрованного пароля. Зтот файл имеет особый формат, определяемый в passwd(5),

и выглядит приблизительно так:

name:pa3swd:uid:gid:gcos:dir:shell

Поля определены следующим образом:

name

Регистрационное имя пользователя

passwd

Зашифрованими пароль или что-нибудь простое, если используется теневой файл паролей

uid

Идентификатор пользователя (для пользователя root — 0, для обычных пользователей — ненулевое число)

gid

Регистрационная группа по умолчанию (группа 0 может быть привиле-гированной, но не обязательно)



gcos

Как правило, содержит полное имя пользователя, за которым через запятую следует и другая информация

dir

Начальний каталог (каталог, в который вы переходите, когда даєте команду cd без аргументов, и в котором хранится большинство ваших файлов, имена которых начинаются с точки)

shell

Ваш регистрационный shell, как правило, /bin/sh

или /Ып/csh (а, может быть, даже /usr/bin/perl,

если вы большой оригинал)

Типичные злементы файла паролей выглядят так:

fred:*:123:15:Fred Flintstone,,,:/home/fred:/bin/csh barney:*:125:15:Barney Rubble,,,:/home/barney:/bin/csh

Сейчас в Perl достаточно инструментов для того, чтобы можно было легко выполнить разбор такой строки (например, с помощью функции split), не прибегая к специальным программам. Тем не менее в библиотеке UNIX все же єсть набор специальных программ: getpwent(3), getpwuid(3), gelpwnam(3) и т.д. Зти программы доступны в Perl под теми же именами, с похожими аргументами и возвращаемыми значеннями.

Например, программа getpwnam в Perl становится функцией getpwnam. Ее единственный аргумент — пользовательское имя (например, fred или barney), а возвращаемое значение — строка файла /etc/passwd, преобра-зованная в массив со следующими значеннями:

($name, $passwd, $uid, $gid, $quota, $cominent, $gcos, $dir, $shell)


Обратите внимание: здесь несколько больше значений, чем в файле паролей. Обычно в UNIX-системах, по крайней мере в тех, которые мы видели, поле $quota всегда пусто, а поля $comment и $gcos часто оба содержат персональную информацию о пользователе (поле GCOS). Так, для старины Фреда мы получаем

("fred", "*", 123, 15, "", "Fred Flintstone,,,", "Fred Flintstone,,,", "/home/gred"," /bin/csh")

посредством любого из следующих вызовов:

getpwuid(123) getpwnam("fred")

Отметим, что в качестве аргумента функция getpwuid принимает иден-тификатор пользователя, a getpwnam — регистрационное имя.

При вьгзове в скалярном контексте функции getpwnam и getpwuid таюке имеют возвращаемое значение — данные, которые вы запросили с их помощью. Например:

$idnum = getpwuid("daemon");

$login °= getpwnam (25);

Возможно, вам захочется получить зти результаты по отдельности, ис-пользуя некоторые из уже знакомых вам операций, проводимых над списками. Один способ — получить часть списка, используя для зтого срез списка, например получить для Фреда только начальний каталог:

($fred home) = (getpwnam ("fred"))[7]; # начальний каталог Фреда

Как просмотреть весь файл паролей? Для зтого можно бьгло бн поступить, к примеру, так:

for($id = 0; $id <= 10_000; $id++) f @stuff = getpwuid $id;

} ### не рекомендуется!

Зто, однако, неверный путь. Наличие нескольких способов само по себе еще не означает, что все они в равной степени зффективны.

Функции getpwuid и getpwnam можно считать функциями произволь-ного доступа; они извлекают конкретний злемент по его ключу, позтому для начала у вас должен быть ключ. Другой метод доступа к файлу паролей — последовательный, т.е. поочередное получение его записей.

Программами последовательного доступа к файлу паролей являются функции setpwent, getpwent и endpwent. В совокупности зти три функции выполняют последовательный проход по всем записям файла паролей. Функция setpwent инициализирует просмотр. После инициализации каж-дый вызов getpwent возвращает следующую запись файла паролей. Если данных для обработки больше нет, getpwent возвращает пустой список. Наконец, вызов endpwent освобождает ресурсы, используемне программой просмотра; зто делается автоматически и при выходе из программы.



Приведенное описание может сказаться не совсем понятным без приме-ра, позтому дадим его:

setpwent (); # инициализировать просмотр while (@list " getpwent ()) ( # выбрать следующий злемент

($login,$home) = @list[0,7]; # получить регистрационное имя # и начальний каталог

print "Home directory for $login is $home\n"; # сообщить зто } endpwent(); # все сделано

Зта программа сообщает имена начальних каталогов всех пользователей, перечисленные в файле паролей. А если вы хотите расставить начальные каталоги в алфавитном порядке? В предыдущей главе мы изучили функцию sort, давайте воспользуемся ею:

setpwentf); # инициализировать просмотр while (@list = getpwentO) ( # вибрать следующий злемент

($login,$home) = @list[0,7]; # долучить регистрационное имя # и начальний каталог

$home($login} = $home; # сохранить их )

endpwent(); # все сделано Skeys = sort ( $home($a( cmp $home($b) } keys %home;

foreach $login (Skeys) ( # пройти по рассортированньпл именам

print "home of $login is $home($login)\n";

}

Зтот несколько более длинный фрагмент иллюстрирует важную особен-ность последовательного просмотра файла паролей: вы можете сохранять соответствующие фрагменты данных в структурах данных, выбираемых по своєму усмотрению. Первая часть примера — зто код просмотра всего файла паролей с созданием хеша, в котором ключ — регистрационное имя, а значение — начальний каталог, соответствующий зтому регистрационному имени. Строка sort получает ключи хеша и сортирует их в соответствии со строковим значением. Завершающий цикл — зто проход по рассортирован-ным ключам и поочередный вывод всех значений.

В общем случае для просмотра небольшого количества значений реко-мендуется использовать программы произвольного доступа (getpwuid и getpwnam). Если значений много или необходим просмотр всех значений, проще выполнить проход с последовательним доступом (с помощью функ-ций setpwent, getpwent и endpwent) и помостить конкретные значення, которые вы будете искать, в хеш*.

Доступ к файлу /etc/group

осуществляется аналогичным образом. После-довательный доступ обеспечивается вызовами функций setgrent, getgrent и endgrent. Вызов getgrent возвращает значення в следующем формате:

<$name, $passwd, $gid, $members)

Зти четыре значення примерно соответствуют четырем полям файла /etc/group,

позтому за подробной информацией обращайтесь к описанням, приведенным на man-страницах, относящихся к формату зтого файла. Соответствующие функций произвольного доступа — getgrgid (по иден-тификатору группы) и getgrnam (по имени группы).

* Если у вас узел с большой NIS-картой, то по соображениям производительности такой способ предобработки файла паролей лучше не использовать.






Содержание раздела