The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

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 passwords
group - 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 users
password - the password itself
realm - 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.