ОБЗОР
#include <netdb.h> /* или <unistd.h> в некоторых системах */
int rcmd(char **ahost, unsigned short inport, const char *locuser,
const char *remuser, const char *cmd, int *fd2p);
int rresvport(int *port);
int iruserok(uint32_t raddr, int superuser,
const char *ruser, const char *luser);
int ruserok(const char *rhost, int superuser,
const char *ruser, const char *luser);
int rcmd_af(char **ahost, unsigned short inport, const char *locuser,
const char *remuser, const char *cmd, int *fd2p,
sa_family_t af);
int rresvport_af(int *port, sa_family_t af);
int iruserok_af(const void *raddr, int superuser,
const char *ruser, const char *luser, sa_family_t af);
int ruserok_af(const char *rhost, int superuser,
const char *ruser, const char *luser, sa_family_t af);
Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):
rcmd(), rcmd_af(), rresvport(), rresvport_af(), iruserok(), iruserok_af(), ruserok(), ruserok_af(): _BSD_SOURCE
ОПИСАНИЕ
Функция rcmd() применяется суперпользователем для исполнения команды на удалённой машине при помощи схемы аутентификации, основанной на зарезервированных номерах портов. Функция rresvport() возвращает файловый дескриптор сокета с адресом в привилегированном пространстве портов. Функции iruserok() и ruserok() используются серверами для аутентификации клиентов, запрашивающих сервис rcmd(). Все четыре функции используются сервером rshd(8) (среди прочих).rcmd()
Функция rcmd() ищет узел *ahost, используя gethostbyname(3) и возвращает -1, если узел не существует. Иначе *ahost устанавливается равным стандартному имени узла, при этом создаётся соединение с сервером на хорошо известном порту Интернет inport.
Если соединение успешно установлено, то вызывающему возвращается сокет в домене Интернет типа SOCK_STREAM, который для удалённой команды считается stdin и stdout. Если fd2p не равно нулю, то устанавливается вспомогательный канал до управляющего процесса, а его файловый дескриптор будет помещён в *fd2p. Управляющий процесс возвращает диагностический вывод из команды (устройства 2) в этот канал, а также принимает байты из этого канала, считая их номерами сигналов UNIX, для их пересылки группе процессов команды. Если fd2p равно 0, то stderr (устройство 2 удалённой команды) будет работать аналогично stdout и для отправки произвольных сигналов в удалённый процесс не будет создано никаких ходов, хотя вы сможете привлечь к себе внимание, используя внеполосную передачу данных.
Протокол подробно описан в rshd(8).
rresvport()
Функция rresvport() используется для получения сокета с привязанным привилегированным портом. Этот сокет подходит для использования функцией rcmd() и некоторыми другими. Привилегированные порты Интернет — это порты с номерами от 0 до 1023. Только привилегированный процесс (CAP_NET_BIND_SERVICE) может привязаться к привилегированному порту. В реализации glibc эта функция ограничена в использовании портов номерами с 512 по 1023. Аргумент port является значением-результатом: передаваемое в вызов значение используется в качестве начальной точки кругового поиска в диапазоне портов; при (успешном) возврате, он содержит номер порта, к которому была осуществлена привязка.
iruserok() и ruserok()
Параметрами функций iruserok() и ruserok() являются, соответственно, IP-адрес или имя удалённого узла, два имени пользователя и флаг, указывающий, является ли имя локального пользователя именем суперпользователя. Далее, если пользователь не является суперпользователем, они проверяют файл /etc/hosts.equiv. Если ничего не находится или завершается с ошибкой, то проверяется .rhosts в домашнем каталоге пользователя (для получения информации о том, разрешены ли запросы к службе).
Если этот файл не существует, не является обычным файлом, если его владельцем является не текущий пользователь или не суперпользователь, или если он доступен для записи кому-то помимо владельца, то проверка завершается с ошибкой. Если имя машины указано в файле hosts.equiv, или если узел и имя пользователя для удалённого доступа найдены в файле .rhosts, то возвращается 0; иначе iruserok() и ruserok() возвращают -1. Если имя локального домена (полученное вызовом gethostname(2)) совпадает с именем удалённого домена, то может указываться только имя машины.
Если IP-адрес удалённого узла известен, то должна использоваться iruserok() вместо ruserok(), так как при этом не требуется доверия к DNS-серверу для домена удалённого узла.
Варианты *_af()
Все описанные ранее функции работают с сокетами IPv4 (AF_INET). Варианты «_af» имеют дополнительный аргумент, который позволяет указать адресное семейство сокета. Для этих функций значением аргумента af может быть AF_INET или AF_INET6. Также rcmd_af() поддерживает использование AF_UNSPEC.ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Функция rcmd() при успешном выполнении возвращает корректный номер дескриптора сокета. При ошибках возвращается -1 и в стандартный поток ошибок выводится диагностическое сообщение.Функция rresvport() при успешном выполнении возвращает корректный привязанный дескриптор сокета. При ошибках возвращается -1 и в глобальную переменную errno записывается код ошибки. Код ошибки EAGAIN означает «Все сетевые порты заняты».
Информацию о результатах ruserok() и iruserok() смотрите выше.
ВЕРСИИ
Функции iruserok_af(), rcmd_af(), rresvport_af() и ruserok_af() появились в glibc начиная с версии 2.2.АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).Интерфейс | Атрибут | Значение |
rcmd(), rcmd_af() | безвредность в нитях | небезопасно (MT-Unsafe) |
rresvport(), rresvport_af() | безвредность в нитях | безвредно (MT-Safe) |
iruserok(),
ruserok(),
iruserok_af(), ruserok_af() | безвредность в нитях | безвредно (MT-Safe locale) |