windows-native-keyring-store 1.0.0

Windows native credential store for keyring
Documentation
/*!

# Windows native credential store for the keyring crate

This module implements a credential store for the keyring crate that uses the
Windows Credential Manager as its back end.

## Usage

To make this store the default for creation of keyring entries, execute this code:
```
keyring_core::set_default_store(windows_native_keyring_store::Store::new().unwrap())
```

## Mapping service and user values to credentials

Each entry in keyring is mapped to a _generic credential_ in the Windows Credential Manager.
The identifier for each credential in Windows is a `target_name` string.  If an entry is created with
an explicit `target` modifier, that value is used as the `target_name`.
Otherwise, a `target_name` string is generated by concatenating a prefix string, the `user`,
a delimiter string, the `service`, and a suffix string.  The prefix, delimiter, and suffix strings
are part of the store configuration.  Their default values are: empty strings for the prefix and suffix,
and a '.' for the delimiter.

Note that service and user strings, by default, can contain the delimiter
string, so it is possible for entries with different service and user strings to
map to the same description (and thus the same credential in the store). If you
are worried about this, you can avoid it by configuring your store to forbid the
delimiter string in the service string.

## Persistence Type

Each generic credential can have one of three persistence types, defined
precisely in the Windows API
[here](https://learn.microsoft.com/en-us/windows/win32/api/wincred/ns-wincred-credentialw),
and represented in this API by the [CredPersist] enumeration values
[Session](CredPersist::Session), [Local](CredPersist::Local), and
[Enterprise](CredPersist::Enterprise).

By default, created credentials have [Enterprise](CredPersist::Enterprise) persistence,
but you can specify a desired persistence by using the `persistence` modifier at entry
creation time with a (case-insensitive) value of `Session`, `Local`, or `Enterprise`. Note
that this type will only be applied when the credential's secret is written; it does not
control the persistence of an existing credential in the store whose value is read via the entry.
The persistence of an existing credential can be read via its `persistence` attribute.

## Attributes

In addition to the `persistence` attribute mentioned in the last section,
there are four string attributes that are held on each generic credential:
`target_name`, `target_alias`, `username`, and `comment`.
The `target_name` attribute is read-only (because it's the unique ID
for the credential in the store).
The `username` attribute in an entry created from a specifier will start
off as the specifier's `user`.
All the attributes on existing credentials can be read using the
[get_attributes](keyring_core::Entry::get_attributes) method, and
their writeable attributes can be set using the
[update_attributes](keyring_core::Entry::update_attributes) method.

## Search

This credential store module supports searching for existing credentials.
You can (optionally) specify a regular-expression `pattern` to be matched against each
credential's `target_name`. If you don't specify a pattern, all existing
generic credentials are returned.

The entries returned from search are all wrappers, of course, but if the
wrapped credential *can* be specified by the store being searched, then
the return entry will also be a specifier. But recall that each store can
have its own conventions for delimiters used when forming the `target_name`.
Thus, a search in one store may return a wrapper/specifier for an existing credential
but that same search in another store may return a wrapper that is *not* a specifier.

## Warnings

Tests show that operating on the same entry from different threads
does not reliably sequence the operations in the same order they
are initiated. (For example, setting a password on one thread and
then immediately spawning another to get the password may return a
`NoEntry` error on the spawned thread.) So be careful not to
access the same entry on multiple threads simultaneously.

Tests show that changing a credential's persistence type
immediately before reading it may cause the read to fail,
especially if the credential manager is busy on multiple
threads.

 */

pub mod cred;
pub use cred::CredPersist;
pub mod store;
pub use store::Store;
#[cfg(test)]
mod tests;
mod utils;