.\" .\" Copyright (c) 2014 Martijn van Duren .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above .\" copyright notice and this permission notice appear in all copies. .\" .\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES .\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF .\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR .\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" .Dd $Mdocdate: September 28 2014 $ .Dt PWSTORE 3 .Os .Sh NAME .Nm pwstore_safe_default , .Nm pwstore_safe_create , .Nm pwstore_safe_open , .Nm pwstore_safe_close , .Nm pwstore_chain_create , .Nm pwstore_chain_open , .Nm pwstore_chain_isopen , .Nm pwstore_chain_modify , .Nm pwstore_chain_close , .Nm pwstore_chain_remove , .Nm pwstore_entry_create , .Nm pwstore_entry_modify , .Nm pwstore_entry_remove , .Nm pwstore_passphrase_retrieve , .Nm pwstore_search_safe , .Nm pwstore_search_chain .Nm passphrase_encrypt .Nm passphrase_decrypt .Nm passphrase_plain_free .Nm passphrase_crypt_free .Nm passphrase_generate .Nd password database management .Sh SYNOPSIS .In pwstore.h .Ft "const char *" .Fo pwstore_safe_default .Fa void .Fc .Ft "struct pwstore_safe *" .Fo pwstore_safe_create .Fa "const char *path" .Fa "const char *passphrase" .Fc .Ft "struct pwstore_safe *" .Fo pwstore_safe_open .Fa "const char *path" .Fa "const char *passphrase" .Fc .Ft void .Fo pwstore_safe_close .Fa "struct pwstore_safe *safe" .Fc .Ft "struct pwstore_chain *" .Fo pwstore_chain_create .Fa "struct pwstore_safe *safe" .Fa "const char *name" .Fa "const char *passphrase" .Fc .Ft int .Fo pwstore_chain_open .Fa "struct pwstore_chain *chain" .Fa "const char *passphrase" .Fc .Ft int .Fo pwstore_chain_isopen .Fa "struct pwstore_chain *chain" .Fc .Ft int .Fo pwstore_chain_modify .Fa "struct pwstore_chain *chain" .Fa "const char *key" .Fa "char *value" .Fc .Ft void .Fo pwstore_chain_close .Fa "struct pwstore_chain *chain" .Fc .Ft int .Fo pwstore_chain_remove .Fa "struct pwstore_chain *chain" .Fc .Ft "struct pwstore_entry *" .Fo pwstore_entry_create .Fa "struct pwstore_chain *chain" .Fc .Ft int .Fo pwstore_entry_modify .Fa "struct pwstore_entry *entry" .Fa "const char *key" .Fa "char *value" .Fc .Ft int .Fo pwstore_entry_remove .Fa "struct pwstore_entry *entry" .Fc .Ft "char *" .Fo pwstore_passphrase_retrieve .Fa "struct pwstore_entry *entry" .Fc .Ft "struct pwstore_entry **" .Fo pwstore_search_safe .Fa "struct pwstore_safe *safe" .Fa "const char *searchstring" .Fc .Ft "struct pwstore_entry **" .Fo pwstore_search_chain .Fa "struct pwstore_chain *chain" .Fa "const char *searchstring" .Fc .In passphrase.h .Ft "struct passphrase *" .Fo passphrase_encrypt .Fa "char *passphrase" .Fc .Ft "char *" .Fo passphrase_decrypt .Fa "const struct passphrase *cryptpassphrase" .Fc .Ft void .Fo passphrase_plain_free .Fa "char *passphrase" .Fc .Ft void .Fo passphrase_crypt_free .Fa "struct passphrase *cryptpassphrase" .Fc .Ft "char *" .Fo passphrase_generate .Fa "int dict" .Fc .Sh DESCRIPTION The pwstore functions are intented for an easy to use api to safely store passphrases in a database and in memory. It is designed to be safe on both storage as well as in memory and is aimed to have the safe file format portable between different processor architectures and Operating Systems. .Ss PWSTORE .Fn pwstore_safe_default returns the default locations for the password database file from the user. .Pp .Fn pwstore_safe_create and .Fn pwstore_safe_open respectively creates a new and opens the existing pwstore database .Fa path with .Fa passphrase for authentication and encryption. Both return a .Ft "struct pwstore_safe *" on success or NULL on failure. On failure errno is set. .Pp .Fn pwstore_safe_close is used to close .Fa safe. This function never fails. .Pp .Fn pwstore_chain_create creates a new chain in .Fa safe with the identifier .Fa name and .Fa passphrase for authentication and encryption. This function returns a .Ft "struct pwstore_chain *" on success and NULL on failure. .Pp .Fn pwstore_chain_open tries to unlock .Fa chain with .Fa passphrase. It returns .Dv PWSTORE_OK on success. If a problem occurs or when the passphase was invalid a .Dv PWSTORE_FAIL is returned. When an invalid chain is supplied it returns with .Dv PWSTORE_INVALID. .Pp .Fn pwstore_chain_isopen checks if .Fa chain is unlocked. It returns 0 on failure or if chain is not a valid chain and 1 on success. .Pp .Fn pwstore_chain_modify modifies an attribute of .Fa chain by setting variable .Fa key to .Fa value. For now only .Dq name is supported. It returns .Dv PWSTORE_OK on success, .Dv PWSTORE_INVAL when .Fa chain is not initialized by the library. .Dv PWSTORE_NOSUP when .Fa key is not supported, and .Dv PWSTORE_FAIL when an internal error occured. .Pp .Fn pwstore_chain_close closes .Fa chain by removing all of entries owned by .Fa chain from memory and nullifying the encryption key. .Pp .Fn pwstore_chain_remove closes the .Fa chain and purges it and its entries from its safe. It returns .Dv PWSTORE_OK on success, .Dv PWSTORE_INVAL when .Fa chain is not initialized by the library, and .Dv PWSTORE_FAIL when it something went wrong. .Pp .Fn pwstore_entry_create creates a new entry in .Fa chain. It returns a .Vt "struct pwstore_entry *" on success or NULL on failure. .Pp .Fn pwstore_entry_modify modifies an attribute of .Fa entry by setting variable .Fa key to .Fa value . The following keys are accepted with their respective values: .Bl -bullet .It .Dq username : the username for this entry. This should be a .Dv \\\0 terminated string of undefined length. .It .Dq passphrase : the passphrase for this entry. This should be a .Dv \\\0 terminated string of undefined length. .It .Dq platform : the platform, service, or protocol for this entry. This should be a .Dv \\\0 terminated string of undefined length. Although no syntax or validity checking is done, it is recommended to use the values from .Xr services 5 . .It .Dq hostname : the hostname of the entry. This is not DNS-checked, but it should speak for itself that this correlation is recommended. .It .Dq address : The address where one should connect to. This can be one of 3 options: .Bl -bullet .It An unix path with a maximum of 104 characters. .It An ipv4 address as can be processed by .Xr inet_pton 3 .It An ipv6 address as can be processed by .Xr inet_pton 3 .El .It .Dq port : The port on which the service is reachable. This value can only be set when address is already set as either an ipv4 or an ipv6 address. In most cases the port can be looked up automatically through .Xr services 5 , but this is not done automatically. .It .Dq comment : an area that can be used to place some extra information regarding the entry. This should be a .Dv \\\0 terminated string of undefined length. .It .Dq from : the date from which this entry is valid. It is stored as a .Vt int64_t and is presented as a .Vt time_t . It should be presented as a string parseable by .Xr strptime 3 . It tries the following options when parsing: .Bl -bullet .It %x .It %F .It %D .El .It .Dq to : the date to which this entry is valid. See from for an explination of the value syntax. .El It returns .Dv PWSTORE_OK on success, .Dv PWSTORE_INVAL when .Fa entry is not initialized by the library, .Dv PWSTORE_NOSUP when .Fa key is not a supported, and .Dv PWSTORE_FAIL when an internal error occured. .Pp .Fn pwstore_entry_remove(struct pwstore_entry *); closes the .Fa entry and purges it from its chain. It returns .Dv PWSTORE_OK on success, .Dv PWSTORE_INVAL when .Fa entry is not initialized by the library, and .Dv PWSTORE_FAIL when it something went wrong. .Pp Because of the sensitivity of a passphrase it is kept inside a shadow within the library. It is retrieved from .Fa entry by calling .Fn pwstore_passphrase_retrieve . Once the passphrase has been used it should be released by calling .Fn passphrase_plain_free . .Pp .Fn pwstore_search_safe and .Fn pwstore_search_chain search the respective .Fa safe and .Fa chain for entries based on .Fa searchstring . The .Fa searchstring follows the following syntax: .Bd = .Ed Where is one of the following keywords: .Bl -bullet .It identifier .It username .It platform .It hostname .It address .It port .It comment .It from .It to .El is the string which has to match. Strings are transformed conforming the same rules as .Fn pwstore_entry_modify before comparing. By using .Sq = an exact match must be made. .Ss PASSPHRASE This set of functions is responsible for keeping a passphrase more or less safe in memory. It encrypts/decrypts passphrase strings with a per session (process) generated key and iv and makes sure that every passphrase that enters plain text is nullified before returning. .Pp .Fn passphrase_encrypt encrypts the NULL terminated string .Fa passphrase and returns a .Vt "struct passphrase *" which contains the encrypted passphrase. Once the application doesn't need this passphrase anymore it should be freed with .Fn passphrase_crypt_free . .Pp .Fn passphrase_decrypt accepts a .Fa "const struct passphrase *" which is decrypted with the session key/iv and returns the plain text passphrase. This plain text string should be erased with .Fn passphrase_plain_free as soon as possible. .Pp .Fn passphrase_plain_free clears the content off the .Fa passphrase as returned by .Fn passphrase_decrypt before releasing it with .Xr free 3 . .Pp .Fn passphrase_crypt_free clears the encrypted .Fa passphrase from memory before releasing it with .Xr free 3 . .Pp .Fn passphrase_generate Generates a new NUL-terminated passphrase. This is done by generating a random string from scratch or by retrieving 2, 3 or 4 random words from .Pa /usr/share/dict/words and catenating them behind each other and turning them to 1337. .Fa dict determines if and how many words are being retrieved from the file. The passphrase should be released with .Xr passphrase_plain_free 3 .Sh EXAMPLES To create a new database with an entry for your mail/imap account you can use the following code: .Bd -literal -offset indent #include struct pwstore_safe *safe; struct pwstore_chain *chain; struct pwstore_entry *entry; // Don't use read only memory, since the passphrase is overwritten after use. char passphrase[] = "mymailpassphrase"; safe = pwstore_safe_create(pwstore_safe_default(), "mysafepassphrase"); chain = pwstore_chain_create(safe, "mail", "mychainpassphrase"); entry = pwstore_entry_create(chain); pwstore_entry_modify(entry, "username", "username@mydomain.com"); pwstore_entry_modify(entry, "passphrase", passphrase); pwstore_entry_modify(entry, "platform", "imap"); pwstore_entry_modify(entry, "hostname", "mail.mydomain.com"); pwstore_entry_modify(entry, "address", "1.3.3.7"); pwstore_entry_modify(entry, "port", "143"); pwstore_entry_modify(entry, "comment", "Just a test entry."); .Ed To retrieve the information from your database you can use the following code: .Bd -literal -offset indent #include #include #include struct pwstore_safe *safe; struct pwstore_chain *chain; struct pwstore_entry **entries; char *passphrase; int i; safe = pwstore_safe_open(pwstore_safe_default(), "mysafepassphrase"); SLIST_FOREACH(chain, (&(safe->pwstore_chains)), entries) { if(strcmp(chain->name, "mail") == 0) break; } pwstore_chain_open(chain, "mychainpassphrase"); entries = pwstore_search_chain(chain, "platform=imap,username=username@mydomain.com"); for(i = 0; entries[i] != NULL; i++) { passphrase = pwstore_passphrase_retrieve(entries[i]); printf("Your passphrase = %s\\n", passphrase); passphrase_plain_free(passphrase); } .Ed .Sh AUTHORS This library was created by .An Martijn van Duren Aq Mt martijn@van.duren.eu .