Главная » 2017 » Ноябрь » 21 » man 2 request_key
01:34
man 2 request_key

SEO sprint - Всё для максимальной раскрутки!





ИМЯ


request_key - запрашивает ключ из системы управления ключами ядра



ОБЗОР


#include <sys/types.h>
#include <keyutils.h>

key_serial_t request_key(const char *type, const char *description,
const char *callout_info,
key_serial_t dest_keyring);

В glibc нет обёрточной функции для данного системного вызова; смотрите ЗАМЕЧАНИЯ.



ОПИСАНИЕ


Системный вызов request_key() пытается найти ключ заданного type с описанием
(именем), совпадающим с description. Если ключ найти невозможно, то ключ может
быть создан. Если ключ найден или создан, то request_key() присоединяет его к
связке ключей, чей идентификатор указан keyring, и возвращает серийный номер
ключа.

Сначала request_key() выполняет рекурсивный поиск совпадающего ключа во всех
связках ключей, присоединённых к вызвавшему процессу. Связки ключей
просматриваются в следующем порядке: связки каждой нити, связки вызвавшего
процесса и связки ключей сеанса.

Если request_key() вызван из программы, вызванной request_key() от имени какого-то
другого процесс для генерации ключа, то в дальнейшем будет осуществлён поиск по
связкам ключей этого другого процесса, используя для определения доступа его
идентификатор пользователя, группы и дополнительных групп и контекста
безопасности.

Поиск в дереве связок ключей выполняется сначала в ширину: искомые ключи в каждой
связке проверяются на совпадение до рекурсивного перехода в дочерние связки
ключей. Найдены могут быть только те ключи, которые разрешены вызывающему для
поиска, и поиск может осуществляться только в разрешённых для поиска связках
ключей.

Если ключ не найден и callout равно NULL, то вызов завершается ошибкой ENOKEY.

Если ключ не найден и callout не равно NULL, то ядро пытается вызвать
пользовательскую программу для создания ключа. Подробности приведены ниже.

Серийный номер dest_keyring может задаваться серийным номером допустимой связки
ключей, на которую у вызывающего есть права на запись, или же это может быть один
из следующих специальных идентификаторов связок ключей:

KEY_SPEC_THREAD_KEYRING
Связка ключей вызывающей нити (смотрите thread-keyring(7)).

KEY_SPEC_PROCESS_KEYRING
Связка ключей вызывающего процесса (смотрите process-keyring(7)).

KEY_SPEC_SESSION_KEYRING
Связка ключей сеанса вызывающего (смотрите session-keyring(7)).

KEY_SPEC_USER_KEYRING
Связка ключей по UID вызывающего (смотрите user-keyring(7)).

определить в какую связку ключей должен быть прицеплен то только что созданный
ключ, оно перебирает связки ключей начиная с со связки, установленной через
keyctl(2) с операцией KEYCTL_SET_REQKEY_KEYRING и продолжает в порядке, показанном
далее, пока не найдёт существующую связку ключей:

· Связка ключей запрашивающего (KEY_REQKEY_DEFL_REQUESTOR_KEYRING, начиная с
Linux 2.6.29).

· Связка ключей нити (KEY_REQKEY_DEFL_THREAD_KEYRING; смотрите
thread-keyring(7)).

· Связка ключей процесса (KEY_REQKEY_DEFL_PROCESS_KEYRING; смотрите
process-keyring(7)).

· Связка ключей сеанса (KEY_REQKEY_DEFL_SESSION_KEYRING; смотрите
session-keyring(7)).

· Связка ключей сеанса для идентификатора пользователя процесса
(KEY_REQKEY_DEFL_USER_SESSION_KEYRING; смотрите user-session-keyring(7)).
Ожидается, что эта связка ключей всегда существует.

· Связка ключей для идентификатора пользователя процесса
(KEY_REQKEY_DEFL_USER_KEYRING; смотрите user-keyring(7)). Ожидается, что эта
связка ключей также всегда существует.

Если вызов keyctl(2) с операцией KEYCTL_SET_REQKEY_KEYRING установил
KEY_REQKEY_DEFL_DEFAULT (или операция KEYCTL_SET_REQKEY_KEYRING не выполнялась),
то ядро ищет связку ключей начиная с начала списка.

Запрос на создание ключа из пользовательского пространства
Если ядро не может найти ключ с соответствующим type и description, и callout не
равно NULL, то ядро пытается вызвать программу из пользовательского пространства
для создания ключа с заданными type и description. В этом случае выполняются
следующие шаги:

а) Ядро создаёт неинициализированный ключ U с запрошенными type и description.

б) Ядро создаёт ключ авторизации V, который ссылается на ключ U и сохраняются
данные вызывающего request_key():

(1) контекст, в котором ключ U должен быть создан и защищён и

(2) контекст, из которого запросы связанного ключа могут быть проведены.

Ключ авторизации создаётся со следующими свойствами:

* Тип ключа — ".request_key_auth".

* UID и GID ключа совпадают с ID в файловой системе для запрашивающего
процесса.

* Ключ даёт права на просмотр, чтение и поиск на ключ-владелец, а также право
просмотра для ключа пользователя.

* Описание (имя) ключа представляет собой Шестнадцатеричную строку
идентификатора ключа, который будет создан в запрашивающей программе.

Данной программе передаются следующие аргументы командной строки:

[0] Строка "/sbin/request-key".

[1] Строка "create" (показывающая, что ключ будет создан).

[2] Идентификатор ключа, который будет создан.

[3] UID (в файловой системе) вызывающего request_key().

[4] GID (в файловой системе) вызывающего request_key().

[5] Идентификатор связки ключей нити вызывающего request_key(). Может быть
ноль, если связка ключей не создана.

[6] Идентификатор связки ключей процесса вызывающего request_key(). Может быть
ноль, если связка ключей не создана.

[7] Идентификатор связки ключей сеанса вызывающего request_key().

Замечание: каждый аргумент командной строки, обозначающий идентификатор ключа,
кодируется десятичным числом (в отличие от идентификаторов ключе, показанных в
/proc/keys, которые выдаются в виде шестнадцатеричных значений).

г) Программа, порождённая на предыдущем шаге:

* Принимает полномочия на создание ключа U с помощью keyctl(2) с операцией
KEYCTL_ASSUME_AUTHORITY (обычно, с помощью функции
keyctl_assume_authority(3)).

* Получает исходящие данные (callout data) из полезной нагрузки ключа
авторизации V (с помощью keyctl(2) с операцией KEYCTL_READ (или, чаще
всего, с помощью функции keyctl_read(3)) с значением идентификатора ключа
KEY_SPEC_REQKEY_AUTH_KEY.

* Создаёт ключ (или выполняет другую программу, которая делает эту работу), с
заданной полезной нагрузкой и связкой ключей назначения (связка ключей
назначения та, которую запрашивающий указал при вызове request_key(), и
которая быть доступна через специальный идентификатор ключа
KEY_SPEC_REQUESTOR_KEYRING). Создание выполняется с помощью keyctl() с
операцией KEYCTL_INSTANTIATE (или, чаще всего, с помощью функции
keyctl_instantiate(3)). На этот момент вызов request_key() завершается и
запрашивающая программа может продолжать выполнение.

Если какой-то из этих шагов завершается ошибкой, то вызвавшему request_key()
возвращается ENOKEY и временно в связку ключей dest_keyring будет установлен
отрицательно инициализированный ключ. Он устареет через несколько секунд, но пока
этого не произойдёт все последующие вызовы request_key() будут завершаться
ошибкой. Целью данного отрицательно инициализированного ключа является
предотвращение повторяющихся запросов (возможно разными) процессами (они требуют
затратных восходящих вызовов request-key(8)) для ключа, который невозможно (в
данный момент) положительно инициализировать.

После инициализации ключа, ключ авторизации (KEY_SPEC_REQKEY_AUTH_KEY) отзывается
и связка ключей назначения (KEY_SPEC_REQUESTOR_KEYRING) становится недоступной
программе request-key(8).

EACCES Изменение связки ключей пользователю недоступно.

EDQUOT Квота на ключи для данного пользователя была бы превышена, если бы этот
ключ создался или был бы прицеплен в связку ключей.

EFAULT Значение type, description или callout_info указывают вне доступного
адресного пространства процесса.

EINTR Запрос был прерван сигналом; смотрите signal(7).

EINVAL Размер строки (включая конечный байт null), заданной в type или
description, превышает ограничение (32 байта и 4096 байт, соответственно).

EINVAL Размер строки (включая конечный байт null), заданной в callout_info,
превышает размер системной страницы.

EKEYEXPIRED
Найден просроченный ключ, и замена не может быть получена.

EKEYREJECTED
Попытка генерации нового ключа была отвергнута.

EKEYREVOKED
Найден отозванный ключ, и замена не может быть получена.

ENOKEY Искомый ключ не найден.

ENOMEM Недостаточно памяти для создания ключа.

EPERM Аргумент type начинается с точки ('.').



ВЕРСИИ


Данный системный вызов впервые появился в Linux 2.6.10. Возможность инициализации
ключей по запросу была добавлена в Linux 2.6.13.



СООТВЕТСТВИЕ СТАНДАРТАМ


Этот системный вызов является нестандартным расширением Linux.



ЗАМЕЧАНИЯ


В glibc нет обёрточной функции для этого системного вызова. Такая функция
предоставляется пакетом libkeyutils. Для работы с функцией подключите библиотеку с
помощью -lkeyutils.



ПРИМЕР


В программе, представленной ниже, показано использование request_key(). Аргументы
type, description и callout_info для системного вызова берутся из значений,
переданных в аргументах командной строки. В качестве связки ключей назначения
вызов использует связку ключей сеанса.

Чтобы показать работу программы сначала нужно создать подходящую запись в файле
/etc/request-key.conf.

$ sudo sh
# echo 'create user mtk:* * /bin/keyctl instantiate %k %c %S' \
> /etc/request-key.conf
# exit


$ ./t_request_key user mtk:key1 "Payload data"
$ grep '2dddaf50' /proc/keys
2dddaf50 I--Q--- 1 perm 3f010000 1000 1000 user mtk:key1: 12

Другой пример смотрите использования этой программы смотрите в keyctl(2).

Исходный код программы

/* t_request_key.c */

#include <sys/types.h>
#include <keyutils.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int
main(int argc, char *argv[])
{
key_serial_t key;

if (argc != 4) {
fprintf(stderr, "Использование: %s тип описание callout-data\n",
argv[0]);
exit(EXIT_FAILURE);
}

key = request_key(argv[1], argv[2], argv[3],
KEY_SPEC_SESSION_KEYRING);
if (key == -1) {
perror("request_key");
exit(EXIT_FAILURE);
}

printf("ID ключа = %lx\n", (long) key);

exit(EXIT_SUCCESS);
}



СМОТРИТЕ ТАКЖЕ


keyctl(1), add_key(2), keyctl(2), keyctl(3), capabilities(7), keyrings(7),
keyutils(7), persistent-keyring(7), process-keyring(7), session-keyring(7),
thread-keyring(7), user-keyring(7), user-session-keyring(7), request-key(8)

Файлы исходного кода ядра Documentation/security/keys/core.rst и
Documentation/keys/request-key.rst (или, до Linux 4.13, файлы
Documentation/security/keys.txt и Documentation/security/keys-request-key.txt).



Категория: (2) Системные вызовы ядра (функции языка Си) | Просмотров: 443 | Добавил: Администратор | Рейтинг: 0.0/0
Всего комментариев: 0
avatar