class Keyutils::Keyring
Constants
- Group
GID-specific keyring
- Process
process-specific keyring
- Session
session-specific keyring @see
Keyutils::SessionKeyring
- Thread
thread-specific keyring
- User
UID-specific keyring
- UserSession
UID-session keyring
Public Class Methods
Get the implicit destination keyring
Gets the default destination for implicit key requests for the current thread.
Keys acquired by implicit key requests, such as might be performed by open() on an AFS or NFS filesystem, will be linked by default to that keyring.
Only one of the special keyrings can be returned:
-
{Thread}
-
{Process}
-
{Session}
-
{User}
-
{UserSession}
-
{Group}
If nil is returned, the default behaviour is selected, which is to use the thread-specific keyring if there is one, otherwise the process-specific keyring if there is one, otherwise the session keyring if there is one, otherwise the UID-specific session keyring.
@return [Keyring, nil] the default keyring @see .default=
# File lib/keyutils/keyring.rb, line 394 def default [nil, Thread, Process, Session, User, UserSession, Group]\ [Lib.keyctl_set_reqkey_keyring -1] end
Set the implicit destination keyring
Sets the default destination for implicit key requests for the current thread.
After this operation has been issued, keys acquired by implicit key requests, such as might be performed by open() on an AFS or NFS filesystem, will be linked by default to the specified keyring by this function.
Only one of the special keyrings can be set as default:
-
{Thread}
-
{Process}
-
{Session}
-
{User}
-
{UserSession}
-
{Group}
If keyring
is nil, the default behaviour is selected, which is to use the thread-specific keyring if there is one, otherwise the process-specific keyring if there is one, otherwise the session keyring if there is one, otherwise the UID-specific session keyring.
@param keyring [Keyring, nil] the new default keyring @return [Keyring, nil] keyring
@see .default
# File lib/keyutils/keyring.rb, line 363 def default= keyring = nil id = keyring.to_i raise ArgumentError, 'only special keyrings can be default' \ if id > 0 Lib.keyctl_set_reqkey_keyring -id end
Get the persistent keyring for a user.
@note Not every system supports persistent keyrings.
Unlike the session and user keyrings, this keyring will persist once all login sessions have been deleted and can thus be used to carry authentication tokens for processes that run without user interaction, such as programs started by cron.
The persistent keyring will be created by the kernel if it does not yet exist. Each time this function is called, the persistent keyring will have its expiration timeout reset to the value in /proc/sys/kernel/keys/persistent_keyring_expiry
(by default three days). Should the timeout be reached, the persistent keyring will be removed and everything it pins can then be garbage collected.
If UID is nil then the calling process's real user ID will be used. If UID is not nil then {Errno::EPERM} will be raised if the user ID requested does not match either the caller's real or effective user IDs or if the calling process does not have SetUid capability.
If successful, a link to the persistent keyring will be added into destination
.
@param uid [Fixnum, nil] UID of the user for which the persistent
keyring is requested
@param destination [Keyring, nil] keyring to add the persistent keyring
to
@return [Keyring] the persistent keyring @raise [Errno::EPERM] not permitted to access the persistent keyring
for the requested UID.
@raise [Errno::ENOMEM] insufficient memory to create the persistent
keyring or to extend +destination+.
@raise [Errno::ENOKEY] destination
does not exist. @raise [Errno::EKEYEXPIRED] destination
has expired. @raise [Errno::EKEYREVOKED] destination
has been revoked. @raise [Errno::EDQUOT] the user does not have sufficient quota to
extend +destination+.
@raise [Errno::EACCES] destination
exists, but does not grant write
permission to the calling process.
@raise [Errno::EOPNOTSUPP] persistent keyrings are not supported by this
system
# File lib/keyutils/keyring.rb, line 441 def persistent uid = nil, destination = nil Keyring.send \ :new, Lib.keyctl_get_persistent(uid || -1, destination.to_i), nil, nil end
Public Instance Methods
Get a member “user” key
Searches the members of the keyring for a :user type key with the given description
@param description [String] description of the key to find @return [Key, nil] the key, if found
# File lib/keyutils/keyring.rb, line 307 def [] description find do |key| key.type == :user && key.description == description rescue false end end
Set a member “user” key
Updates or creates a member key of type “user” and given description
@param description [String] the description of the key to update or
create
@param payload [String] the new key payload @return [String] payload
# File lib/keyutils/keyring.rb, line 321 def []= description, payload add :user, description, payload end
Add a key to the kernel's key management facility.
Asks the kernel to create or update a key of the given type
and description
, instantiate it with the payload
, and to attach it to this keyring.
The key type may reject the data if it's in the wrong format or in some other way invalid.
Keys of the user-defined key type (“user”) may contain a blob of arbitrary data, and the description may be any valid string, though it is preferred that the description be prefixed with a string representing the service to which the key is of interest and a colon (for instance “afs:mykey”).
If this keyring already contains a key that matches the specified type and description then, if the key type supports it, that key will be updated rather than a new key being created; if not, a new key will be created and it will displace the link to the extant key from the keyring.
@param type [Symbol] key type @param description [String] key description @param payload [#to_s, nil] payload @return [Key] the key created or updated @raise [Errno::ENOKEY] the keyring doesn't exist @raise [Errno::EKEYEXPIRED] the keyring has expired @raise [Errno::EKEYREVOKED] the keyring has been revoked @raise [Errno::EINVAL] the payload data was invalid @raise [Errno::ENODEV] the key type was invalid @raise [Errno::ENOMEM] insufficient memory to create a key @raise [Errno::EDQUOT] the key quota for this user would be exceeded by
creating this key or linking it to the keyring
@raise [Errno::EACCES] the keyring wasn't available for modification by
the user
# File lib/keyutils/keyring.rb, line 233 def add type, description, payload serial = Lib.add_key \ type.to_s, description, payload && payload.to_s, payload && payload.to_s.length || 0, to_i Key.send :new_dispatch, serial, type.intern, description end
Clear the contents of the keyring.
The caller must have write permission on a keyring to be able clear it. @return [Keyring] self @raise [Errno::ENOKEY] the keyring is invalid @raise [Errno::EKEYEXPIRED] the keyring has expired @raise [Errno::EKEYREVOKED] the keyring had been revoked @raise [Errno::EACCES] the keyring is not writable by the calling process
# File lib/keyutils/keyring.rb, line 16 def clear Lib.keyctl_clear id self end
Iterate over linked keys
@return [Enumerator, Keyring] self if block given, else an Enumerator @yieldparam key [Key] member of the keyring @see read
# File lib/keyutils/keyring.rb, line 147 def each &b read.each &b end
Iterate over keys recursively
Performs a depth-first recursive scan of the keyring tree and yields for every link found in the accessible keyrings in that tree.
Errors are ignored. Inaccessible keyrings are not scanned, but links to them are still yielded. If key attributes (and hence ype) cannot be retrieved, a generic {Key} object is yielded and an error that prevented it is indicated.
This method yields for each link found in all the keyrings in the tree and so may be called multiple times for a particular key if that key has multiple links to it.
@yieldparam key [Key] the key to which the link points @yieldparam parent [Keyring, nil] the keyring containing the link or nil
for the initial key.
@yieldparam attributes [Hash] key attributes, as returned by
{Key#describe}
@yieldparam error [SystemCallError, nil] error that prevented retrieving
key attributes
@return [Enumerator, Keyring] self if block given, else an Enumerator
# File lib/keyutils/keyring.rb, line 174 def each_recursive return enum_for __method__ unless block_given? Lib.recursive_key_scan serial, ->(parent, key, desc, desc_len, _) do parent = parent == 0 ? nil : Keyring.send(:new, parent, nil) if desc_len > 0 attributes = Key.send :parse_describe, desc.read_string(desc_len) key = Key.send :new_dispatch, key, attributes[:type], attributes[:desc] error = nil else attributes = nil key = Key.send :new, key, nil, nil error = SystemCallError.new FFI.errno end yield key, parent, attributes, error 0 end, nil self end
@return [Fixnum] number of keys linked to this keyring
# File lib/keyutils/keyring.rb, line 195 def length read.length end
Link a key to the keyring.
Creates a link from this keyring to key
, displacing any link to another key of the same type and description in this keyring if one exists.
The caller must have write permission on a keyring to be able to create links in it.
The caller must have link permission on a key to be able to create a link to it.
@param key [Key] the key to link to this keyring @return [Keyring] self @raise [Errno::ENOKEY] the key or the keyring specified are invalid @raise [Errno::EKEYEXPIRED] the key or the keyring specified have expired @raise [Errno::EKEYREVOKED] the key or the keyring specified have been
revoked
@raise [Errno::EACCES] the keyring exists, but is not writable by the
calling process
@raise [Errno::ENOMEM] insufficient memory to expand the keyring @raise [Errno::EDQUOT] expanding the keyring would exceed the keyring
owner's quota
@raise [Errno::EACCES] the key exists, but is not linkable by the
calling process
@see unlink
# File lib/keyutils/keyring.rb, line 46 def link key Lib.keyctl_link key.id, id self end
Read the keyring.
Reads the list of keys in this keyring.
The caller must have read permission on a key to be able to read it.
@return [<Key>] the keyring members @raise [Errno::ENOKEY] the keyring is invalid @raise [Errno::EKEYEXPIRED] the keyring has expired @raise [Errno::EKEYREVOKED] the keyring had been revoked @raise [Errno::EACCES] the keyring is not readable by the calling process @see each
Keyutils::Key#read
# File lib/keyutils/keyring.rb, line 132 def read super.unpack('L*').map do |serial| # try to map to the correct class key = Key.send :new, serial, nil, nil Key.send(:new_dispatch, serial, key.type, key.description) rescue key end end
Request a key from the kernel's key management facility.
Asks the kernel to find a key of the given type
that matches the specified description
and, if successful, to attach it this keyring.
{#request} first recursively searches all the keyrings attached to the calling process in the order thread-specific keyring, process-specific keyring and then session keyring for a matching key.
If {#request} is called from a program invoked by request_key(2) on behalf of some other process to generate a key, then the keyrings of that other process will be searched next, using that other process's UID, GID, groups and security context to control access.
The keys in each keyring searched are checked for a match before any child keyrings are recursed into. Only keys that are searchable for the caller may be found, and only searchable keyrings may be searched.
If the key is not found then, if callout_info
is not nil, this function will attempt to look further afield. In such a case, the callout_info
is passed to a user-space service such as /sbin/request-key
to generate the key.
If that is unsuccessful also, then an error will be raised, and a temporary negative key will be installed in the keyring. This will expire after a few seconds, but will cause subsequent calls to {#request} to fail until it does.
If a key is created, no matter whether it's a valid key or a negative key, it will displace any other key of the same type and description from the keyring. @param type [Symbol] key type @param description [String] key description @param callout_info [String, nil] additional parameters for the
request-key(8) facility
@return [Key, nil] the key, if found @raise [Errno::EACCES] the keyring wasn't available for modification by the user @raise [Errno::EINTR] the request was interrupted by a signal @raise [Errno::EDQUOT] the key quota for this user would be exceeded by creating this key or linking it to the keyring @raise [Errno::EKEYEXPIRED] an expired key was found, but no replacement could be obtained @raise [Errno::EKEYREJECTED] the attempt to generate a new key was rejected @raise [Errno::EKEYREVOKED] a revoked key was found, but no replacement could be obtained @raise [Errno::ENOMEM] insufficient memory to create a key @see Keyring#search
@see man7.org/linux/man-pages/man2/request_key.2.html request_key(2) @see assume_authority
# File lib/keyutils/keyring.rb, line 289 def request type, description, callout_info = '' serial = Lib.request_key \ type.to_s, description, callout_info, to_i new_dispatch serial, type.intern, description rescue Errno::ENOKEY nil end
Search the keyring for a key
Recursively searches the keyring for a key of the specified type
and description
.
If found, the key will be attached to the destination
keyring (if given), and returned.
The source keyring must grant search permission to the caller, and for a key to be found, it must also grant search permission to the caller. Child keyrings will be only be recursively searched if they grant search permission to the caller as well.
If the destination
keyring is given, then the link may only be formed if the found key grants the caller link permission and the destination keyring grants the caller write permission.
If the search is successful, and if the destination keyring already contains a link to a key that matches the specified type and description, then that link will be replaced by a link to the found key.
@param type [Symbol] the type of the key to find @param description [String] the description of the key to find @param destination [Keyring, nil] the keyring to attach the key if found @return [Key, nil] the key, if found @raise [Errno::EKEYEXPIRED] one of the keyrings has expired, or the only
key found was expired
@raise [Errno::EKEYREVOKED] one of the keyrings has been revoked, or the
only key found was revoked
@raise [Errno::ENOMEM] insufficient memory to expand the destination
keyring
@raise [Errno::EDQUOT] the key quota for this user would be exceeded by
creating a link to the found key in the destination keyring
@raise [Errno::EACCES] the source keyring didn't grant search permission,
the destination keyring didn't grant write permission or the found key didn't grant link permission to the caller
@see request
# File lib/keyutils/keyring.rb, line 113 def search type, description, destination = nil serial = Lib.keyctl_search id, type.to_s, description, destination.to_i Key.send :new_dispatch, serial, type.intern, description rescue Errno::ENOKEY nil end
Return all “user” subkeys
Keys that cannot be read are ommited.
@return [{String => String}] user keys' descriptions and their payloads
# File lib/keyutils/keyring.rb, line 330 def to_h keys = find_all { |k| k.type == :user rescue false } pairs = keys.map { |k| [k.description, k.to_s] rescue nil } Hash[*pairs.compact.flatten] end
Unlink a key from the keyring.
Removes a link from this keyring to key
if it exists.
The caller must have write permission on a keyring to be able to remove links in it. @param key [Key] the key to unlink from this keyring @return [Keyring] self @raise [Errno::ENOKEY] the key or the keyring specified are invalid @raise [Errno::EKEYEXPIRED] the key or the keyring specified have expired @raise [Errno::EKEYREVOKED] the key or the keyring specified have been
revoked
@raise [Errno::EACCES] the keyring exists, but is not writable by the
calling process
@see link
# File lib/keyutils/keyring.rb, line 68 def unlink key Lib.keyctl_unlink key.id, id self rescue Errno::ENOENT # there was no link self end