ОПИСАНИЕ
Средство
управления
ключами Linux
позволяет
различным
компонентам
ядра
хранить
или
кэшировать
охраняемые
безопасности,
ключи
аутентификации,
ключи
шифрования
и другие
данные в
ядре.
Через
системные
вызовы
пользовательские
программы
могут
управлять
этими
объектами,
а также
использовать
это
средство
для своих
собственных
целей;
смотрите
add_key(2), request_key(2) и keyctl(2).
Для
работы с
данными
предоставляется
библиотека
и
пользовательские
программы.
Подробности
смотрите в
keyctl(1), keyctl(3) и keyutils(7).
Ключи
Ключ
имеет
следующие
атрибуты:
- Серийный
номер (ID)
- Уникальное
целое
число,
используется
в
системных
вызовах
для ссылки
на ключ.
- тип
- Тип ключа
определяет
какие
данные
можно
хранить в
ключе, как
будет
обрабатываться
содержимое
ключа и как
будут
использованы
полезные (payload)
данные.
- Доступно
несколько
типов
ключей
общего
назначения,
а также
специальные
типы,
определённые
компонентами
ядра.
- Описание
(имя)
- Описание
ключа —
пригодная
для печати
строка,
которая
используется
в условии
поиска
ключа
(вместе с
типом), а
также как
отображаемое
имя. При
поиске
описание
может
совпадать
как
полностью
так и
частично.
- Полезные
данные (payload)
- Полезные
данные это
то, что
хранит
ключ.
Обычно, они
указываются
при
создании
ключа, но
возможно,
что для
завершения
создания
ядро
сделает
запрос в
пользовательское
пространство,
если ключ
был
неизвестен
ядру до
запроса.
Подробности
смотрите в
request_key(2).
- Полезные
данные
ключа
можно
читать и
изменять,
если это
поддерживается
типом
ключа и у
вызывающего
есть
права.
- Права
доступа
- Much as files do, each key has an owning user ID, an owning group ID, and
a security label. Each key also has a set of permissions, though there are
more than for a normal UNIX file, and there is an additional
category—possessor—beyond the usual user, group, and other
(see Possession, below).
- Заметим,
что на
ключи
действуют
квоты, так
как для них
требуется
невытесняемая
память
ядра. Квота
списывается
с
пользовательского
ID
владельца.
- Срок
действия
- Каждый
ключ имеет
срок
действия.
Когда срок
заканчивается,
ключ
помечается
как
просроченный
и доступ к
нему
завершается
ошибкой
EKEYEXPIRED. Если
его не
удалить,
изменить
или
заменить,
то после
заданного
количества
времени
просроченный
ключ
автоматически
удаляется
(сборка
мусора)
вместе со
всеми
ссылками
на него и
попытка
доступа к
ключу
завершается
ошибкой
ENOKEY.
- Число
ссылок
- У каждого
ключа есть
счётчик
ссылок. На
ключи
ссылаются
из связок
ключей,
принадлежащих
активным
на данный
момент
пользователям
и из
мандатов
процесса.
Когда
счётчик
ссылок
становится
равным
нулю, ключ
планируется
для сборки
мусора.
Типы
ключей
Ядро
предоставляет
несколько
основных
типов
ключей:
- "keyring"
- Связки
ключей —
это
специальные
ключи,
которые
хранят
набор
ссылок на
другие
ключи
(включая
другие
связки
ключей),
так же как
каталоги
хранят
ссылки на
файлы.
Основное
предназначение
связки
ключей — не
дать
другим
ключам
попасть в
мусор по
причине
того, что
они нигде
не
используются.
- Keyrings with descriptions (names) that begin with a period ('.') are
reserved to the implementation.
- "user"
- Тип ключа
общего
назначения.
Ключ
полностью
находится
в памяти
ядра.
Полезные
данные
можно
читать и
изменять
из
пользовательских
приложений.
- Полезные
данные
ключей
этого типа
представляют
собой
данные
произвольной
структуры
(blob) размером
до 32767 байт.
- The description may be any valid string, though it is preferred that it
start with a colon-delimited prefix representing the service to which the
key is of interest (for instance "afs:mykey").
- "logon"
(начиная с Linux
3.3)
- This key type is essentially the same as "user", but it
does not provide reading (i.e., the keyctl(2) KEYCTL_READ
operation), meaning that the key payload is never visible from user space.
This is suitable for storing username-password pairs that should not be
readable from user space.
- The description of a "logon" key must start with a
non-empty colon-delimited prefix whose purpose is to identify the service
to which the key belongs. (Note that this differs from keys of the
"user" type, where the inclusion of a prefix is
recommended but is not enforced.)
- "big_key"
(начиная с Linux
3.13)
- This key type is similar to the "user" key type, but it
may hold a payload of up to 1 MiB in size. This key type is useful
for purposes such as holding Kerberos ticket caches.
- Данные
полезной
нагрузки
может
сохраняться
в файловой
системе tmpfs, а
не в памяти
ядра, если
размер
данных
превышает
накладные
расходы на
хранение
данных в
файловой
системе
(хранение
данных в
файловой
системе
требует
выделения
места в
ядре под
структуры
файловой
системы.
Размер
этих
структур
определяется
размером
границы,
после
которой
используется
хранение в
tmpfs). Начиная с
Linux 4.8, данные
полезной
нагрузки
при
хранении в
tmpfs
шифруются
и, таким
образом, не
записываются
в
пространство
подкачки в
не
шифрованном
виде.
Существуют
также
другие
специальные
типы
ключей, но
здесь они
не описаны,
так как не
предназначены
для
использования
в обычном
пользовательском
пространстве.
Key type names that begin with a period ('.') are reserved to the
implementation.
Связки
ключей
Как
упоминалось
ранее,
связки
ключей
являются
специальным
типом
ключей,
которые
содержат
ссылки на
другие
ключи
(которые
могут
включать
другие
связки
ключей).
Ключи
могут быть
связаны с
несколькими
связками
ключей.
Связки
ключей
могут
считаться
аналогом
каталогов
UNIX, где в
каждом
каталоге
содержится
набор
жёстких
ссылок на
файлы.
Операции
(системные
вызовы)
применяемые
только к
связкам
ключей:
- Добавление
- Ключ может
добавляться
в связку
ключей
системным
вызовом,
создающим
ключи. Это
предотвращает
немедленное
удаление
нового
ключа
после того,
как
системный
вызов
удаляет
свою
последнюю
ссылку на
ключ.
- Присоединение
- В связку
ключей
может быть
добавлена
ссылка,
которая
указывает
на уже
известный
ключ, при
этом
контролируется
отсутствие
ссылок на
саму
связку.
- Отсоединение
- Ссылка
может быть
удалена из
связки
ключей. При
удалении
последней
ссылки на
ключ, он
планируется
к удалению
сборщиком
мусора.
- Очистка
- Из связки
ключей
могут
удаляться
все
ссылки.
- Поиск
- Связка
ключей
может
считаться
корнем
дерева или
поддерева
в котором
связки
ключей
считаются
ветвями, а
обычные
ключи —
листьями. В
таком
дереве
может
выполнять
поиск
ключа по
типу и
описанию.
Подробности
смотрите в
keyctl_clear(3), keyctl_link(3), keyctl_search(3)
и keyctl_unlink(3).
Закрепляющие
ключи
Если ключ
не
используется
ядром,
чтобы не
быть
удалённым
сборщиком
мусора, он
должен
быть
закреплён
для
сохранения
положительного
значения
своего
счётчика
ссылок.
Для
закрепления
ключей
используются
связки
ключей:
каждая
связь
представляет
ссылку на
ключ.
Заметим,
что сами
связки
ключей —
тоже ключи
и требуют
закрепления,
чтобы не
быть
удалёнными
сборщиком
мусора.
В ядре
доступно
несколько
закрепляющих
связок
ключей.
Заметим,
что
некоторые
из них
будут
созданы
только в
момент
первого
обращения.
- Связки
ключей
процесса
- Мандаты
процесса
являются
связками
ключей со
специальной
семантикой.
Эти связки
ключей
существуют
пока
существуют
мандаты, то
есть,
обычно,
пока
существует
процесс.
- Существует
три связки
ключей с
различными
правилами
наследования/общего
пользования:
session-keyring(7)
(наследуется
и
используется
всеми
дочерними
процессами),
process-keyring(7)
(используется
всеми
нитями
процесса) и
thread-keyring(7)
(доступна
только
определённой
нити).
- Альтернативой
использованию
реальных ID
связок
ключей в
вызовах
add_key(2), keyctl(2) и request_key(2)
можно
указывать
значения
специальных
связок
ключей
KEY_SPEC_SESSION_KEYRING, KEY_SPEC_PROCESS_KEYRING и
KEY_SPEC_THREAD_KEYRING,
которые
ссылаются
на
экземпляры
ключей,
принадлежащие
вызывающему.
- Пользовательские
связки
ключей
- Для
каждого UID,
известного
ядру,
имеется
запись,
содержащая
две связки
ключей: user-keyring(7)
и user-session-keyring(7). Они
существуют
пока в ядре
существует
запись UID.
- Альтернативой
использованию
реальных ID
связок
ключей в
вызовах
add_key(2), keyctl(2) и request_key(2)
можно
указывать
значения
специальных
связок
ключей
KEY_SPEC_USER_KEYRING и
KEY_SPEC_USER_SESSION_KEYRING,
которые
ссылаются
на
экземпляры
ключей,
принадлежащие
вызывающему.
- Ссылка на
пользовательскую
связку
ключей
помещается
в связку
ключей
нового
сеанса с
помощью
pam_keyinit(8) в
момент
начала
нового
сеанса
входа.
- Постоянные
связки
ключей
- Для
каждого UID
системы
доступна
persistent-keyring(7). Она
может
существовать
и после
окончания
жизни
записи UID,
упомянутой
ранее, но
её срок
службы
устанавливается
таким
образом,
чтобы она
автоматически
очищалась
после
указанного
времени.
Постоянные
связки
ключей
позволяют,
например,
сценариям
cron(8)
использовать
мандаты,
остающиеся
в
постоянной
связке
ключей
после
выхода
пользователя.
- Заметим,
что срок
службы
постоянной
связки
ключей
сбрасывается
каждый раз
после
запроса
постоянной
связки
ключей.
- Специальные
связки
ключей
- Существуют
специальные
связки
ключей,
принадлежащие
ядру,
которые
могут
хранить
закрепляющие
ключи для
специальных
целей.
Например,
system keyring
используется
для
хранения
ключей
шифрования
для модуля
сличения
подписи.
- Эти
специальные
связки
ключей,
обычно,
закрыты
для
прямого
изменения
из
пользовательского
пространства.
Первоначально
планировавшиеся
«групповые
связки
ключей»
для
хранения
ключей,
связанных
с каждым GID,
известным
ядру, пока
не
реализованы,
и, вероятно,
не будут.
Тем не
менее, для
этой
связки
ключей
определена
константа
KEY_SPEC_GROUP_KEYRING.
Владение
(possession)
Концепция
владения
важна для
понимания
модели
безопасности
связки
ключей.
Владеет ли
нить
ключом
определяется
следующими
правилами:
- (1)
- Ключ или
связка
ключей, на
которую у
вызывающего
нет права
поиска,
игнорируется
во всех
последующих
правилах.
- (2)
- Нить
непосредственно
владеет
своими
session-keyring(7), process-keyring(7) и
thread-keyring(7), так
как на эти
связки
ключей
есть
ссылка из
её
мандатов.
- (3)
- Если
связкой
ключей
кто-то
владеет, то
он владеет
всеми
ключами в
связке.
- (4)
- Если ключ в
связке
связан сам
с собой в
связке, то
правило (3)
применяется
рекурсивно.
- (5)
- Если
процесс
вызван из
ядра для
создания
ключа
(смотрите
request_key(2)), то оно
также
владеет
связкой
ключей
вызвавшего
как в
правиле (1)
если бы он
был
вызывающим.
Заметим,
что
владение
не
является
фундаментальным
свойством
ключа и
вычисляется
каждый раз
при
необходимости.
Механизм
владения
разработан
для того,
что бы
программы
с set-user-ID,
запускаемые,
например,
из
оболочки,
имели
доступ к
пользовательским
ключам.Права
предоставляются
владельцу
ключа, в то
время как
доступ к
ключам по UID
и GID ключа не
дают
такого
доступа.
Когда
создаётся
связка
ключей
сеанса, pam_keyinit(8)
добавляет
связь с user-keyring(7),
то есть по
умолчанию
даёт право
владения
пользовательской
связкой
ключей и
всем её
содержимым.
Права
доступа
Каждый
ключ имеет
следующие
атрибуты,
относящиеся
к
безопасности:
- •
- Пользовательский
идентификатор
владельца
- •
- Идентификатор
группы,
которой
разрешён
доступ к
ключу
- •
- Метка
безопасности
- •
- Маска
доступа
Маска
доступа
содержит
четыре
набора
прав.
Первые три
набора
взаимоисключающие.
Только по
одному из
них
выполняются
определённые
проверки.
Есть три
набора
прав, в
порядке
уменьшения
приоритета:
- пользователь
- Набор
предоставляемых
прав, если
пользовательский
ID ключа
совпадает
с
пользовательским
ID
вызывающего
из
файловой
системы.
- группа
- Набор
предоставляемых
прав, если
пользовательский
ID ключа не
совпадает
и
групповой
ID ключа
совпадает
с GID
вызывающего
из
файловой
системы
или одним
из GID его
дополнительных
групп.
- остальные
- Набор
предоставляемых
прав, если
не
совпадает
ни
пользовательский
ID, ни
групповой
ID ключа.
Четвёртый
набор
прав:
- владелец
- Набор
предоставляемых
прав, если
определено,
что ключом
владеет
вызывающий.
Полный
набор прав
на ключ
представляет
собой
объединение
одного из
первых
трёх
наборов и
четвёртого
набор, если
для ключа
задано
владение.
Набор
прав,
который
может быть
предоставлен
каждой из
четырёх
масок:
- просмотр
- Для чтения
доступны
атрибуты
ключа. К
ним
относятся
тип,
описание и
права
доступа
(кроме
метки
безопасности).
- чтение
- Для ключа:
можно
читать
полезные
данные
ключа. Для
связки
ключей:
можно
читать
список
серийных
номеров
(ключей), с
которыми
связка
ключей
имеет
связь.
- запись
- Можно
изменять
полезные
данные и
отзывать
ключ. Для
связки
ключей:
можно
добавлять
и удалять
связи из
связки
ключей, а
также
полностью
очищать
связку
ключей
(удаление
всех
связей).
- поиск
- Для ключа
(или связки
ключей):
ключ можно
найти
поиском.
Для связки
ключей:
можно
найти
ключи и
связки
ключей,
связанные
в связку
ключей.
- связь
- Из связки
ключей
можно
установить
связь с
ключом. Для
начальной
связи с
ключом,
устанавливаемой
при
создании
ключа,
этого не
требуется.
- установка
атрибутов
- Можно
изменять
атрибуты
владения и
метку
безопасности,
задавать
срок
действия
ключа и
отзывать
ключ.
Кроме
прав,
доступ к
ключа
также быть
заблокирован
любым
активным
модулем
безопасности
Linux(LSM), если это
прописано
в его
политике.
Ключу LSM
может
назначить
метку
безопасности
или другой
атрибут;
эту метку
можно
получить с
помощью
keyctl_get_security(3).
Подробности
смотрите в
keyctl_chown(3), keyctl_describe(3),
keyctl_get_security(3), keyctl_setperm(3) и
selinux(8).
Поиск
ключей
Одним из
основных
свойств
управления
ключами Linux
является
возможность
поиска
ключей,
хранимых
процессом.
Системный
вызов request_key(2)
является
основным
методом
для
приложений
пользовательского
пространства
для поиска
ключа (для
использования
ключей во
внутренних
компонентах
у ядра есть
что-то
похожее).
Алгоритм
поиска
работает
так:
- (1)
- The process keyrings are searched in the following order: the
thread-keyring(7) if it exists, the process-keyring(7) if it
exists, and then either the session-keyring(7) if it exists or the
user-session-keyring(7) if that exists.
- (2)
- Если
вызывающий
является
процессом,
который
был вызван
механизмом
верхнего
вызова 9upcall)
request_key(2), то
связки
ключей
первоначального
вызывающего
также
будут
просматриваться
request_key(2).
- (3)
- Поиск в
дереве
связки
ключей
выполняется
«сначала
вширь»: в
каждой
связка
ключей
просматривается
до первого
совпадения,
затем
просматриваются
связки
ключей, на
которые
ссылается
эта связка
ключей.
- (4)
- Если
найденный
ключ
действителен,
то поиск
завершается
и
возвращается
этот ключ.
- (5)
- Если
найденный
ключ
находится
в
состоянии
ошибки, то
это
состояние
ошибки
запоминается
и поиск
продолжается.
- (6)
- Если
действительный
ключ не
найден, то
возвращается
первое
запомненное
состояние
ошибки; в
противном
случае
возвращается
ошибка ENOKEY.
Также
можно
проводить
поиск в
определённой
связке
ключей, в
этом
случае
выполняются
только
шаги с (3) по (6).
Подробности
смотрите в
request_key(2) и keyctl_search(3).
Создание
ключа по
требованию
Если ключ
невозможно
найти, то
request_key(2), если
указан
аргумент
callout_info,
создаст
новый ключ
и затем
сделает
вызов в
пользовательское
пространство
для его
инициализации.
Это
позволяет
создавать
ключи
только при
необходимости.
Как
правило,
при этом
ядро
создаёт
новый
процесс с
выполняемой
программой
request-key(8),
которая, в
свою
очередь,
запустит
соответствующий
обработчик
в
соответствии
со своими
настройками.
Обработчику
передаётся
специальный
ключ
авторизации,
который
позволяет
только
этому
обработчику
инициализировать
новый ключ.
Он также
используется
для
разрешения
поиска,
выполняемого
программой-обработчиком,
в связках
ключах
запрашивающего.
Подробности
смотрите в
request_key(2), keyctl_assume_authority(3),
keyctl_instantiate(3), keyctl_negate(3),
keyctl_reject(3), request-key(8) и
request-key.conf(5).
Пользователи
Система
управления
ключами Linux
содержит
некоторое
количество
пользователей
и свойств,
но не
ограничивается
только
ими.
Ядерные
пользователи
этого
свойства:
- Сетевые
файловые
системы — DNS
- Ядро
использует
механизм
внешнего
вызова (upcall),
предоставляемый
ключами, из
пользовательского
пространства
для
выполнения
поиска в DNS и
кэширования
результатов.
- AF_RXRPC и kAFS
—
аутентификация
- Сетевой
протокол AF_RXRPC
и ядерная
файловая
система AFS
использует
ключи для
хранения
билетов,
необходимых
для работы
с
безопасным
и
шифрованным
трафиком.
Позднее
эти билеты
ищутся
сетевыми
операциями
AF_RXRPC и
операциями
файловой
системы kAFS.
- NFS —
отображение
идентификаторов
пользователей
- Файловая
система NFS
используется
ключи для
хранения
отображений
идентификаторов
сторонних
пользователей
в
идентификаторы
локальных
пользователей.
- CIFS —
пароль
- Файловая
система CIFS
используется
ключи для
хранения
паролей
доступа к
удалённым
общим
ресурсам.
- Поверка
модуля
- Процесс
сборки
ядра может
криптографически
подписывать
модули. В
последствии
эта
подпись
проверяется
при
загрузке
модуля.
Пользователи
пространства
пользователя
этого
свойства:
- Хранилище
ключей Kerberos
- Средство MIT
Kerberos 5 (libkrb5) может
использовать
ключи для
хранения
токенов
аутентификации,
которые
при
задании
времени
могут
автоматически
очищаться
после
последнего
обращения
пользователя,
но
оставаться
даже после
выхода
пользователя
для того,
чтобы их
можно было
использовать
из
сценариев
cron(8).