Class: Keyutils::Keyring
- Includes:
- Enumerable
- Defined in:
- lib/keyutils/keyring.rb,
lib/keyutils/keyring.rb
Constant Summary collapse
- Thread =
thread-specific keyring
Keyring.new Lib::KEY_SPEC[:THREAD_KEYRING], nil
- Process =
process-specific keyring
Keyring.new Lib::KEY_SPEC[:PROCESS_KEYRING], nil
- Session =
session-specific keyring
Keyring.new(Lib::KEY_SPEC[:SESSION_KEYRING], nil). extend SessionKeyring
- User =
UID-specific keyring
Keyring.new Lib::KEY_SPEC[:USER_KEYRING], nil
- UserSession =
UID-session keyring
Keyring.new Lib::KEY_SPEC[:USER_SESSION_KEYRING], nil
- Group =
GID-specific keyring
Keyring.new Lib::KEY_SPEC[:GROUP_KEYRING], nil
Instance Attribute Summary
Attributes inherited from Key
Class Method Summary collapse
-
.default ⇒ Keyring?
Get the implicit destination keyring.
-
.default=(keyring = nil) ⇒ Keyring?
Set the implicit destination keyring.
-
.persistent(uid = nil, destination = nil) ⇒ Keyring
Get the persistent keyring for a user.
Instance Method Summary collapse
-
#[](description) ⇒ Key?
Get a member “user” key.
-
#[]=(description, payload) ⇒ String
Set a member “user” key.
-
#add(type, description, payload) ⇒ Key
Add a key to the kernel’s key management facility.
-
#clear ⇒ Keyring
Clear the contents of the keyring.
-
#each {|key| ... } ⇒ Enumerator, Keyring
Iterate over linked keys.
-
#each_recursive {|key, parent, attributes, error| ... } ⇒ Enumerator, Keyring
Iterate over keys recursively.
-
#length ⇒ Fixnum
Number of keys linked to this keyring.
-
#link(key) ⇒ Keyring
(also: #<<)
Link a key to the keyring.
-
#read ⇒ <Key>
(also: #to_a)
Read the keyring.
-
#request(type, description, callout_info = '') ⇒ Key?
Request a key from the kernel’s key management facility.
-
#search(type, description, destination = nil) ⇒ Key?
Search the keyring for a key.
-
#to_h ⇒ {String => String}
Return all “user” subkeys.
-
#unlink(key) ⇒ Keyring
Unlink a key from the keyring.
Methods inherited from Key
#==, #assume_authority, #chown, #describe, #description, #eql?, #exists?, find, #gid, #instantiate, #invalidate, #perm, #reject, renounce_authority, #revoke, #security, #serial, #set_timeout, #setperm, #type, #uid, #update
Class Method Details
.default ⇒ Keyring?
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:
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.
394 395 396 397 |
# File 'lib/keyutils/keyring.rb', line 394 def default [nil, Thread, Process, Session, User, UserSession, Group]\ [Lib.keyctl_set_reqkey_keyring -1] end |
.default=(keyring = nil) ⇒ Keyring?
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:
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.
363 364 365 366 367 368 |
# 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 |
.persistent(uid = nil, destination = nil) ⇒ Keyring
Not every system supports persistent keyrings.
Get the persistent keyring for a user.
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
.
441 442 443 444 445 446 447 |
# 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 |
Instance Method Details
#[](description) ⇒ Key?
Get a member “user” key
Searches the members of the keyring for a :user type key with the given description
307 308 309 310 311 |
# File 'lib/keyutils/keyring.rb', line 307 def [] description find do |key| key.type == :user && key.description == description rescue false end end |
#[]=(description, payload) ⇒ String
Set a member “user” key
Updates or creates a member key of type “user” and given description
321 322 323 |
# File 'lib/keyutils/keyring.rb', line 321 def []= description, payload add :user, description, payload end |
#add(type, description, payload) ⇒ Key
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.
233 234 235 236 237 238 239 240 241 |
# 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 ⇒ Keyring
Clear the contents of the keyring.
The caller must have write permission on a keyring to be able clear it.
16 17 18 19 |
# File 'lib/keyutils/keyring.rb', line 16 def clear Lib.keyctl_clear id self end |
#each {|key| ... } ⇒ Enumerator, Keyring
Iterate over linked keys
147 148 149 |
# File 'lib/keyutils/keyring.rb', line 147 def each &b read.each &b end |
#each_recursive {|key, parent, attributes, error| ... } ⇒ Enumerator, Keyring
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 Keyutils::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.
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# 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 |
#length ⇒ Fixnum
Returns number of keys linked to this keyring.
195 196 197 |
# File 'lib/keyutils/keyring.rb', line 195 def length read.length end |
#link(key) ⇒ Keyring Also known as: <<
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.
46 47 48 49 |
# File 'lib/keyutils/keyring.rb', line 46 def link key Lib.keyctl_link key.id, id self end |
#read ⇒ <Key> Also known as: to_a
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.
132 133 134 135 136 137 138 |
# 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(type, description, callout_info = '') ⇒ Key?
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.
289 290 291 292 293 294 295 296 297 298 |
# 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(type, description, destination = nil) ⇒ Key?
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.
113 114 115 116 117 118 |
# 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 |
#to_h ⇒ {String => String}
Return all “user” subkeys
Keys that cannot be read are ommited.
330 331 332 333 334 |
# 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(key) ⇒ Keyring
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.
68 69 70 71 72 73 74 |
# 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 |