Passwd::Keyring backend API
This document describes the API Passwd::Keyring::Something
modules should implement to be usable via Passwd::Keyring::Auto
and to be easily swappable.
API
new
Passwd::Keyring::Backend->new();
Passwd::Keyring::Backend->new(app=>'some app', group=>'passwords group/folder', %other_args);
The constructor initializes the backend, and constructs the object via which the further processing is to happen.
The constructor should perform sufficient initialization to ensure it can work properly and should fail (croak
or die
) in case given backend is not available (for example because some daemon is not running or some app not installed).
The Passwd::Keyring::Auto
module may try loading and initiating a few keyring types, and settle on the first which loaded and constructed succesfully.
Named arguments should be accepted and handled, but are all optional (the module should work without them providing some sane defaults). Two of those are standarized:
app
- the name of the application using the library to store passwordsgroup
- the name of folder/group/pack/...
app
should be used as the calling application name in any interactive prompts, if they may happen (for example in KDEWallet's "Application X is asking to ..." prompt). If possible, it should also be used in some comment or label field of secure storage, but not inside a key (it should be possible to save the password under one app name, and recover using another app name, after all a few apps may share some password).
group
should be used to separate the passwords (entries for the password of the same user in the same realm, but with different group
, should be separate), and - if only possible - to label the password in secure storage. Preferrable implementation is to use group
for folder name if secure storage has some notion of folders.
Note also PARAMETER SYNTAX section below.
If app
and/or group
are not specified, some sensible defaults should be applied (like Passwd::Keyring::Backend
for application name and Passwd::Keyring::Passwords
for group).
Backend is free to handle any other named arguments, but should function properly if they are omitted.
set_password
$keyring->set_password("John", "verysecret", "gmail.com");
Persistently set and save the password (or update previously saved password).
The method takes 3 arguments:
user_id
- in most cases actually the user login id of a kind, but in general any identifier allowing to distinguish between different userspassword
- the password itselfrealm
- indicator of the kind/target of the password. In (frequent) case of internet passwords, it can be the domain name of web application, but backend should not assume any specific format.
In case underlying API places strict requirements on format of any of those values, the backend should appropriately modify them (escape, prefix, wrap, ...) to be as forgiving, as possible. Note also PARAMETER SYNTAX section below.
The only strict requirement is that get_password
appropriately matches those operation, and that different user_id
or realm
(or group
given in constructor) leads to separate password.
If possible, password should be labelled using parameters set in the constructor.
Actual key for the password should be built from group
given in new
, realm
and user_id
. Changing any of those params should mean separate password.
get_password
$keyring->get_password("John", "gmail.com");
Reads previously saved password. The routine takes two arguments:
user_id
realm
and should recover the exact password which was saved with the same user_id
and realm
(and group
) by earlier call to set_password
.
In case no such password was saved, the method should return undef
.
If set_password
performed any kind of escaping, get_password
should revert it's effects. Note also PARAMETER SYNTAX section below.
clear_password
$keyring->clear_password("John", "some password identifier");
Remove previously saved password. The routine takes two arguments:
user_id
realm
and should wipe password for this key if it is saved (and do nothing otherwise).
is_persistent
if( $keyring->is_persistent() ) {
# ...
}
This helper method should return 1 (or any true boolean value) if passwords are really saved persistently and will be available after the program is terminated.
Most backends are expected to provide this guarantee (and return 1), emergency backends like Passwd::Kering::Memory
return 0.
Additional requirements
PARAMETER SYNTAX
Keyring backends should be permissive with respect to application name, group name, username, password and realm syntax. This means escaping or replacing possibly illegal characters (for example, if some implementation dislikes /
in realm, it should escape it somehow).
In particular, complete visible ASCII set (letters, digits, spaces, interpunction including slashes, dollars and hashes etc) should be accepted, and also non-latin letters.
If there are serious limitations on length of those parameters, they should be carefully documented. By default it is assumed up to 256 chars can be used for any param.
USING MULTIPLE KEYRINGS WITHIN ONE PROGRAM
If possible, keyring objects should behave sensibly if more than one object is created within single program (do not crash, do not destroy data, share updates).
If this is impossible or difficult, it is recommended to disallow creation many objects (throw an exception on attempt to create second one).
Multithreading
Single keyring object is not required to provide any multithreading guarantees, users are expected to perform appropriate locking.
Separate keyring objects should function sensibly when simultaneously used in different threads. If this is difficult, the backend should not allow to create many objects in single program.
Multiple processes
Keyring objects should work properly when a few processes try to use the same data simultaneously.
In all practical cases this guarantee should be provided by underlying secure storage API.