|
Программирование >> Структура ядра и системные вызовы
setpwent о; for ( struct passwd *pwd; pwd=getpwent(); ) cout pwd->pw name , UID: pwd->pw uid , , GID: pwd->pw gid endl; endpwent(); return 0; Функция fgetpwent подобна функции getpwent, с той лишь разницей, что в ней пользователь задает указатель на файл с такой же структурой, как у файла /etc/passwd. Эта функция возвращает пользовательские учетные данные, находящиеся в следующей записи файла. Функции setpwent и endpwent с функцией fgetpwent не используются. 4.12. <grp.h> в заголовке <grp.h> определяется набор функций, предназначенных для получения учетной информации о группах, содержащейся в UNIX-файле /etc/group. Здесь объявляются следующие функции: const struct group* getgrnam (const char* group name ); const struct group* getgrgid (consX int gid ); int setgrent ( void ); const struct group* getgrent (void ); int endgrent ( void ); const struct group* fgetgrent (¥\LE* fptr ); Тип данных struct group определен в файле заголовков <§ф.Ь> так: struct group { char* char* int char** gr name; имя группы gr passwd; зашифрованный пароль группы gr gid; идентификатор группы gr comment; имена членов группы Каждая запись struct group содержит данные из одной строки файла /etc/group. Эта строка содержит информацию о бюджете одной группы в UNIX-системе. В частности, это имя группы, назначенный идентификатор группы и список имен входящих в нее пользователей. Функция getgrnam принимает в качестве аргумента имя группы и возвращает указатель на запись типа struct group, которая содержргг информацию о группе, если эта группа определена в системе. Если заданное имя группы недействрггельно, функция возвращает NULL-указатель. Определить идентификатор группы developer можно следующим образом: struct group *grp = getgrnam( developer ); if ( !grp ) cerr developer is not valid group on this systemXn ; else cout grp->gr name , GID= grp->gr gid endl; Функция getgrgid принимает в качестве аргумента идентификатор группы и возвращает указатель на запись типа struct group, которая содержит информацию об этой группе, если группа определена в системе. Если заданный идентификатор группы недействителен, функция возвращает NULL-указатель. Информацию о членах группы с идентификатором 200 можно получить с помощью следующего выражения: struct group *grp = getgrgid( 200 ); if ( !grp ) cerr 200 is not valid GID on this system\n ; else for (int i=0; grp->pw comment && grp->pw comment[i]; i++ ) cout grp->gr comment[i] endl; Функция setgrent устанавливает указатель чтения файла на начало файла /etc/group. Функция getgrwent смещает этот указаталь на следующую запись файла /etc/group. Когда с помощью функции getgrwent будет осуществлен просмотр всех записей в каталоге/etc/passwd, она возвратит NULL-указатель, что обозначает конец файла. Для закрытия файла /etc/group вызывается функция endgrent. Программа testjgrp.C направляет на стандартный вывод перечень всех зарегистрированных в системе групп с их идентификаторами: ♦include <iostream.h> ♦include <grp.h> int main() { setgrent 0 ; for ( struct group *grp; grp=getgrent() ; ) cout grp->gr name , GID: grp->gr gid endl; endgrent 0; return 0; Функция fgetgrent подобна функции getgrent, за исключением того что в ней пользователь задает указатель на файл, имеющий такой же синтаксис, что и файл /etc/group. Эта функция возвращает учетные данные группы, находящиеся в текущей записи данного файла. Функции setgrent и endgrent с функцией fgetgrent не используются. 4.13. <crypt.h> в заголовке <crypt.h> объявляется набор функций, предназначенных для шифрования и дешифрования данных. Это очень важные функции, обеспе-чиваюшие безопасность системы. Например, файлы пользовательских паролей и системных данных, которым необходима высокая степень зашиты, должны быть зашифрованы так, чтобы ни один человек, не имеюший специального разрешения, не мог узнать, что они из себя представляют. Более того, чтобы читать и изменять эти объекты, уполномоченные лица * должны знать секретные ключи дешифровки. В заголовке <crypt.h> объявляются следующие функции:
Функция crypt используется в UNIX-системах для шифрования пользовательских паролей и проверки действительности регистрационного пароля пользователя. Эта функция принимает два аргумента. Первый аргумент, key, является паролем, определенным пользователем. Второй аргумент, salt, применяется для идентификации полученной зашифрованной строки. Значение аргумента salt состоит из двух символов, взятых из следующего набора: a-z, A-Z, 0-9, / Если функция crypt вызывается гфоцессом password для шифрования нового пароля пользователя, то процесс возвращает случайное значение salt. Полученная строка, зашифрованная и снабженная уникальным идентификатором, имеет следующий формат: <salt><зaшифpoвaннaя строка пароля> Затем, когда пользователь пытается зарегистрироваться в системе, указывая имя и пароль, регистрационный процесс проверяет аутентичность пользователя следующим образом: tinclude <iostream.h> tinclude <crypt.h> tinclude <pwd.h> tinclude <string.h> int check login{ const char* user name, const char* password) ( struct passwd* pw; if ( !{pw=getpwnam( user name )) ) { cerr Invalid login name: user name endl; return 0; не аутентичен char* newjpw = crypt( password, pw->pw passwd ); if ( strcmp { new pw,pw->pw passwd ) ) { ,4, cerr Invalid password: password endl; return 0; не аутентичен ,) \ У /* имя пользователя и пароль действительны */ return 1 В этом примере функция checkjogin вызывается для того, чтобы убедиться, что указанное регистрационное имя пользователя и пароль действительны. Функция возвращает 1, если они действительны, О - если нет. Данная функция вызывает функцию getpwnam для преобразования указанного имени пользователя в указатель на запись типа struct passwd. Если имя пользователя действительно, то функция getpwnam возвращает значение, отличное от NULL. Если нет - она возвращает значение NULL, а функция checkjogin возвращает код ошибки. После получения записи типа struct passwd функция checkjogin для шифрования данного пароля вызывает функцию crypt. /Аргумент salt, указанный в вызове crypt, находится в поле pwjpasswd записи типа struct passdw. Первыми двумя символами зашифрованного пароля пользователя являются символы, заданные аргументом salt, который был использован для создания зашифрованного пароля. Возвращаемое значение crypt является зашифрованной строкой пароля, и оно сравнивается со значением pw passwd. Если они совпадают, то данный пароль действителен, в противном случае функция checkjogin возвращает код ошибки. Как следует из сказанного, функция crypt не расшифровывает строки, тем не менее она может быть использована для шифрования новой строки и последующего ее сравнения со старой с целью проверки содержания последней. Необходимо отметить, что первые два символа шифрованной строки - это символы, заданные аргументом salt, который использовался для ее создания. Если две одинаковые строки зашифровать с различными значениями salt, то зашифрованные строки будут различаться. Функции setkey и encrypt выполняют действия, аналогичные действию функции crypt, однако они используют алгоритм шифрования данных по стандарту DES Национального бюро стандартов США (NBS), который более надежен, чем алгоритм, используемый функцией crypt. Аргумент функции setkey - это массив символов, состоящий из 64 элементов. Каждый из этих элементов должен содержать целое значение 1 или О, которое является одним битом из восьмибайтового значения salt. Первый аргумент key функции encrypt является символьным массивом, состоящим из 64 элементов. Каждый из этих элементов содержит один бит из восьмибайтового значения key, которое должно быть зашифровано (если значение третьего аргумента flag - 0) или расшифровано (если значение flag - 1). Полученная зашифрованная или расшифрованная строка передается обратно в вызывающую функцию, изменяя значение ее аргумента key. Функция encrypt может обрабатывать максимум восемь символов за один вызов. 4.14. Заключение в этой главе описываются библиотечные функции ANSI С и некоторые библиотечные функции С, характерные для ОС UNIX. Стандартными классами С++ и интерфейсами прикладного программирования UNIX и POSIX они не охватываются. Зная эти функции, пользователь может сократить время разработки приложений, добиться высокого уровня переносимости программного обеспечения и значительно уменьшить затраты на сопровождение конечного продукта. Возможность использования некоторых из этих библиотечных функций продемонстрирована на ряде примеров. Как уже было сказано, описанные библиотечные функции имеют один недостаток: их ассортимент и возможности недостаточны для разработки приложений системного уровня. Для создания таких приложений необходимо использовать интерфейсы прикладного программирования UNIX и POSIX. Эти API описываются в других главах нашей книги, где освешается методика их использования в системном программировании и приводятся примеры применения для реализации некоторых стандартных библиотечных функций С, упомянутых в настояшей главе. ГЛАВА иг- Интерфейсы прикладного программирования UNIX и POSIX В UNIX-системах имеется набор функций API (широко известных как системные вызовы), которые могут вызываться программами пользователей для выполнения специфических системных задач. Эти функции позволяют пользовательским приложениям непосредственно манипулировать системными объектами типа файлов и процессов, чего нельзя сделать, используя только стандартные библиотечные функции С. Кроме того, многие команды UNIX, библиотечные функции С и стандартные классы С++ (например, класс iostream) вызывают эти интерфейсы прикладного программирования для фактического выполнения необходимой работы. Таким образом, с помошью этих API пользователи могут избежать издержек, связанных с вызовом библиотечных функций С и стандартных классов С++, и создавать свои собственные версии команд UNIX, библиотечных функций С и классов С++. В большинстве UNIX-систем имеется обший набор API для решения следующих задач: определения конфигурации системы и получения информации о пользователях; манипулирования файлами; создания процессов и управления ими; осуществления межпроцессного взаимодействия; обеспечения связи по сети. Большинство API ОС UNIX обращаются к внутренним ресурсам ядра UNIX. Так, когда один из этих API вызывается процессом (процесс -
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |