# HG changeset patch # User Guido Berhoerster # Date 1427299823 -3600 # Node ID e1309515d111733e471f600eba4370f461a7e2e6 # Parent d541e748cfd8594b3fa24d7601622a9f85a2ddf6 Add README file and manpages diff -r d541e748cfd8 -r e1309515d111 Makefile --- a/Makefile Tue Feb 10 11:29:54 2015 +0100 +++ b/Makefile Wed Mar 25 17:10:23 2015 +0100 @@ -45,6 +45,45 @@ PAX := pax GZIP := gzip SED := sed +XSLTPROC := xsltproc +DOCBOOK5_MANPAGES_STYLESHEET = http://docbook.sourceforge.net/release/xsl-ns/current/manpages/docbook.xsl +DOCBOOK5_MANPAGES_FLAGS = --stringparam funcsynopsis.style 'ansi' \ + --stringparam man.authors.section.enabled 0 \ + --stringparam man.copyright.section.enabled 0 +DOCBOOK5_XHTML_STYLESHEET = http://docbook.sourceforge.net/release/xsl-ns/current/xhtml/docbook.xsl +DOCBOOK5_XHTML_FLAGS = --stringparam funcsynopsis.style 'ansi' \ + --stringparam generate.consistent.ids 1 \ + --stringparam refentry.generate.name 1 \ + --stringparam refentry.generate.title 0 \ + --stringparam refentry.xref.manvolnum 1 \ + --stringparam generate.id.attributes 1 \ + --stringparam make.valid.html 1 \ + --stringparam make.clean.html 1 \ + --stringparam html.cleanup 1 \ + --stringparam html.longdesc 0 \ + --stringparam ulink.target '' \ + --stringparam docbook.css.source '' \ + --stringparam css.decoration 0 \ + --stringparam default.table.width '100%' + +define generate-manpage-rule = +$(addsuffix .%,$(basename $1)): $(addsuffix .%.xml,$(basename $(firstword $1))) docbook-update-source-data.xsl + $$(XSLTPROC) \ + --xinclude \ + --stringparam package $$(PACKAGE) \ + --stringparam version $$(VERSION) \ + docbook-update-source-data.xsl $$< | \ + $$(XSLTPROC) \ + --xinclude \ + --output $(firstword $1) \ + $$(DOCBOOK5_MANPAGES_FLAGS) \ + $$(DOCBOOK5_MANPAGES_STYLESHEET) \ + - + $$(SED) 's,^\.HP \\w.*$$$$,.HP 4n,' $$@ >$$(@).tmp && mv $$(@).tmp $$@ + for alias in $(wordlist 2,$(words $1),$1); do \ + ln -sf $(notdir $(firstword $1)) $$$$alias; \ + done +endef DESTDIR ?= prefix ?= /usr/local @@ -104,11 +143,78 @@ OBJS = $(LIBPWS_OBJS) +LIBPWS_MANPAGES = libpws.3 + +PWS_INIT_MANPAGES = pws_init.3 \ + pws_finalize.3 \ + pws_set_alloc_functions.3 \ + pws_generate_uuid.3 + +PWS3_FILE_CREATE_MANPAGES = pws3_file_create.3 \ + pws3_file_destroy.3 \ + pws3_file_get_error_code.3 \ + pws3_file_get_error_message.3 \ + pws3_file_read_mem.3 \ + pws3_file_read_stream.3 \ + pws3_file_write_mem.3 \ + pws3_file_write_stream.3 \ + pws3_file_set_header_field.3 \ + pws3_file_get_header_field.3 \ + pws3_file_remove_header_field.3 \ + pws3_file_insert_empty_group.3 \ + pws3_file_get_empty_group.3 \ + pws3_file_remove_empty_group.3 \ + pws3_file_first_empty_group.3 \ + pws3_file_last_empty_group.3 \ + pws3_file_next_empty_group.3 \ + pws3_file_prev_empty_group.3 \ + pws3_file_insert_record.3 \ + pws3_file_get_record.3 \ + pws3_file_remove_record.3 \ + pws3_file_first_record.3 \ + pws3_file_last_record.3 \ + pws3_file_next_record.3 \ + pws3_file_prev_record.3 \ + pws3_field_create.3 \ + pws3_field_destroy.3 \ + pws3_field_is_header.3 \ + pws3_field_get_type.3 \ + pws3_field_get_data_type.3 \ + pws3_field_set_uuid.3 \ + pws3_field_set_text.3 \ + pws3_field_set_time.3 \ + pws3_field_set_uint8.3 \ + pws3_field_set_uint16.3 \ + pws3_field_set_uint32.3 \ + pws3_field_set_bytes.3 \ + pws3_field_get_uuid.3 \ + pws3_field_get_text.3 \ + pws3_field_get_time.3 \ + pws3_field_get_uint8.3 \ + pws3_field_get_uint16.3 \ + pws3_field_get_uint32.3 \ + pws3_field_get_bytes.3 \ + pws3_record_create.3 \ + pws3_record_destroy.3 \ + pws3_record_set_field.3 \ + pws3_record_get_field.3 \ + pws3_record_remove_field.3 + +MANPAGES = $(LIBPWS_MANPAGES) \ + $(PWS_INIT_MANPAGES) \ + $(PWS3_FILE_CREATE_MANPAGES) + +XHTML_DOCUMENTATION = $(addsuffix .xhtml,$(firstword $(LIBPWS_MANPAGES)) \ + $(firstword $(PWS_INIT_MANPAGES)) \ + $(firstword $(PWS3_FILE_CREATE_MANPAGES))) + .DEFAULT_TARGET = all .PHONY: all clean clobber dist install -all: $(LIBPWS_LIB) +all: $(LIBPWS_LIB) $(MANPAGES) + +doc: $(MANPAGES) $(XHTML_DOCUMENTATION) XCPPFLAGS = -Iinclude ifeq ($(HAVE_ARC4RANDOM),1) @@ -146,6 +252,12 @@ $(LIBPWS_LIB): $(LIBPWS_LIB_MEMBERS) +$(eval $(call generate-manpage-rule,$(LIBPWS_MANPAGES))) + +$(eval $(call generate-manpage-rule,$(PWS_INIT_MANPAGES))) + +$(eval $(call generate-manpage-rule,$(PWS3_FILE_CREATE_MANPAGES))) + %.o: %.c $(MAKEDEPEND.c) $< | $(SED) -f deps.sed >$*.d $(COMPILE.c) -o $@ $< @@ -154,16 +266,39 @@ $(AR) $(ARFLAGS) $@ $< $(RANLIB) $@ +%.xhtml: %.xml docbook-update-source-data.xsl + $(XSLTPROC) \ + --xinclude \ + --stringparam package $(PACKAGE) \ + --stringparam version $(VERSION) \ + docbook-update-source-data.xsl $< | \ + $(XSLTPROC) \ + --xinclude \ + --output $@ \ + $(DOCBOOK5_XHTML_FLAGS) \ + $(DOCBOOK5_XHTML_STYLESHEET) \ + - + install: for header in include/*.h; do \ $(INSTALL.data) $${header} \ - "$(DESTDIR)$(includedir)/$(PACKAGE)/$${header##*/}"; \ + "$(DESTDIR)$(includedir)/$${header##*/}"; \ done $(INSTALL.lib) $(LIBPWS_LIB) \ "$(DESTDIR)$(libdir)/$(notdir $(LIBPWS_LIB))" + for manpage in $(MANPAGES); do \ + if [ -L $${manpage} ]; then \ + $(INSTALL.link) $${manpage} \ + "$(DESTDIR)$(mandir)/man$${manpage##*.}/$${manpage##*/}"; \ + else \ + $(INSTALL.data) $${manpage} \ + "$(DESTDIR)$(mandir)/man$${manpage##*.}/$${manpage##*/}"; \ + fi \ + done clean: - rm -f $(LIBPWS_LIB) $(LIBPWS_OBJS) + rm -f $(LIBPWS_LIB) $(LIBPWS_OBJS) $(MANPAGES) \ + $(XHTML_DOCUMENTATION) clobber: clean rm -f $(patsubst %.o,%.d,$(OBJS)) diff -r d541e748cfd8 -r e1309515d111 README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Wed Mar 25 17:10:23 2015 +0100 @@ -0,0 +1,103 @@ +libpws +======= + +Description +----------- + +libpws provides an API for creating, reading, manipulating and writing +Password Safe files, it currently supports version 3 of the Password Safe file +format. + +Build Instructions +------------------ + +libpws requires a POSIX:2004 compatible operating system, it has been tested +to work on Linux distributions, FreeBSD, Solaris and Illumos-derived +distributions. The following tools and shared libraries are required to build +libpws: + +- GNU make >= 3.81 +- GNU or BSD install +- Nettle + +Rebuilding the man pages additionally requires the xsltproc tool from libxml2. + +Before building libpws check the commented macros in the Makefile for any +macros you may need to override depending on the used toolchain and operating +system. + +By default, all files will be installed under the "/usr/local" directory, a +different installation path prefix can be set via the `prefix` macro. In +addition, a second path prefix can be specified via the `DESTDIR` macro which +will be prepended to any path, incuding the `prefix` macro path prefix. In +contrast to `prefix`, the path specified via the `DESTDIR` macro will only be +prepended to paths during installation and not be used for constructing +internal paths. + +The following instructions assume that `make` is GNU make, on some platforms +it may be installed under a different name or a non-default path. In order to +start the build process run `make all`. After a successful build, run `make +install` to install the program, any associated data files and the +documentation. + +Previously built binaries, object files, generated data files and +documentation can be removed by running `make clean`, any additional, +generated files which are not removed by the `clean` target can be removed by +running `make clobber`. + +Contact +------- + +Please send any feedback, translations or bug reports via email to +. + +Bug Reports +----------- + +When sending bug reports, please always mention the exact version of libpws +with which the issue occurs as well as the version of the operating system you +are using and make sure that you provide sufficient information to reproduce +the issue and include any input, output, any error messages. + +In case of build issues, please also specify the implementations and versions +of the tools and shared libraries used to build the program, in particular the +compiler. + +In case of crashes, please generate a stack trace with a suitable debugger +such as gdb, lldb, dbx, or debug after a crash has occurred either by +examining the resulting core file or by running the program from the debugger +and attach it to the bug report. In order to generate a meaningful stack +trace the program as well as any dynamically linked libraries need to be built +with debugging information, see the documentation of the used compiler for the +required compiler flags. If any of the dynamically linked shared libraries do +not contain debugging information, please either install debugging information +for these libraries using mechanisms provided by your operating system or +rebuild the libraries accordingly. Please refer to the documentation of the +debugger for detailed instructions on generating backtraces. + +License +------- + +Except otherwise noted, all files are Copyright (C) 2015 Guido Berhoerster and +distributed under the following license terms: + +Copyright (C) 2015 Guido Berhoerster + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff -r d541e748cfd8 -r e1309515d111 docbook-update-source-data.xsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/docbook-update-source-data.xsl Wed Mar 25 17:10:23 2015 +0100 @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + diff -r d541e748cfd8 -r e1309515d111 libpws.3.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libpws.3.xml Wed Mar 25 17:10:23 2015 +0100 @@ -0,0 +1,213 @@ + + + + + + + Guido + Berhoerster + + guido+libpws@berhoerster.name + + + 21 March, 2015 + + + libpws + 3 + + + Library Functions + + + libpws + library for creating and manipulating Password Safe files + + + + cc + + + + + + + + + + + + + + + + + + +#include <pws.h> + + + + + Description + libpws provides an API for creating, reading, manipulating and + writing Password Safe files. The Password Safe file format is intended + for the platform-independent secure storage of passwords and associated + metadata and offers protection from unauthorized access to the file by + encrypting it using a key derived from a master password. Its design + ensures both confidentiality and integrity of its contents. + libpws currently supports version 3 of the Password Safe file + format. + The <pws.h> header provides type and + function declarations for all library services. + With the exception of pws_set_alloc_functions + all functions are reentrant. Functions operating on a Password Safe file + structure, a header field structure, a record field structure, and a record + structure provide no locking. A multithreaded application must either + provide its own synchronization mechanisms or restrict operations on any of + the above structures to a single thread. + + + Interfaces + The static library libpws.a + provides following the public interfaces: + + pws_init + pws_finalize + pws_set_alloc_functions + pws_generate_uuid + pws3_field_create + pws3_field_destroy + pws3_field_is_header + pws3_field_get_type + pws3_field_get_data_type + pws3_field_set_uuid + pws3_field_set_text + pws3_field_set_time + pws3_field_set_uint8 + pws3_field_set_uint16 + pws3_field_set_uint32 + pws3_field_set_bytes + pws3_field_get_uuid + pws3_field_get_text + pws3_field_get_time + pws3_field_get_uint8 + pws3_field_get_uint16 + pws3_field_get_uint32 + pws3_field_get_bytes + pws3_file_create + pws3_file_destroy + pws3_file_get_error_code + pws3_file_get_error_message + pws3_file_read_mem + pws3_file_read_stream + pws3_file_write_mem + pws3_file_write_stream + pws3_file_set_header_field + pws3_file_get_header_field + pws3_file_remove_header_field + pws3_file_insert_empty_group + pws3_file_get_empty_group + pws3_file_remove_empty_group + pws3_file_first_empty_group + pws3_file_last_empty_group + pws3_file_next_empty_group + pws3_file_prev_empty_group + pws3_file_insert_record + pws3_file_get_record + pws3_file_remove_record + pws3_file_first_record + pws3_file_last_record + pws3_file_next_record + pws3_file_prev_record + + It defines the following C preprocessor macros which are documented + in the + pws_init3 + manual page: + + LIBPWS_VERSION_MAJOR + LIBPWS_VERSION_MINOR + LIBPWS_VERSION_MICRO + PWS3_VERSION + PWS3_MAX_FIELD_SIZE + PWS3_MAX_PASSWORD_LEN + PWS3_UUID_SIZE + + + + Types + libpws provides the following data structures: + + + struct pws3_file + + Opaque data structure representing a Password Safe version 3 + file. + + + + struct pws3_record + + Opaque data structure representing a Password Safe version 3 + record. + + + + struct pws3_field + + Opaque data structure representing a Password Safe version 3 + typed field belonging to the header or a record, depending on the + type it may hold a UUID, string, time, 8-bit, 16-bit, or 32-bit + wide unsigned integer or raw data. + + + + + + Security + The aforementioned protection of confidentiality and integrity of + the file contents only applies to the stored file. When reading a Password + Safe file using libpws, the file contents are decrypted and stored in + memory where they might be compromised, e.g. by a malicious application or + a privileged user. Furthermore, parts of the process memory may be paged to + the swap area by the operating system. + libpws provides hooks for allocating and freeing memory used to + store sensitive information which may be used to mitigate such issues + using operating system specific facilities. + libpws has not been formally audited, use at your own risk. + + + See Also + pws_init + 3, + pws3_file_create + 3, + + diff -r d541e748cfd8 -r e1309515d111 pws3_file_create.3.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pws3_file_create.3.xml Wed Mar 25 17:10:23 2015 +0100 @@ -0,0 +1,1400 @@ + + + + + + + Guido + Berhoerster + + guido+libpws@berhoerster.name + + + 21 March, 2015 + + + libpws + 3 + + + Library Functions + + + pws3_file_create + pws3_file_destroy + pws3_file_get_error_code + pws3_file_get_error_message + pws3_file_read_mem + pws3_file_read_stream + pws3_file_write_mem + pws3_file_write_stream + pws3_file_set_header_field + pws3_file_get_header_field + pws3_file_remove_header_field + pws3_file_insert_empty_group + pws3_file_get_empty_group + pws3_file_remove_empty_group + pws3_file_first_empty_group + pws3_file_last_empty_group + pws3_file_next_empty_group + pws3_file_prev_empty_group + pws3_file_insert_record + pws3_file_get_record + pws3_file_remove_record + pws3_file_first_record + pws3_file_last_record + pws3_file_next_record + pws3_file_prev_record + pws3_field_create + pws3_field_destroy + pws3_field_is_header + pws3_field_get_type + pws3_field_get_data_type + pws3_field_set_uuid + pws3_field_set_text + pws3_field_set_time + pws3_field_set_uint8 + pws3_field_set_uint16 + pws3_field_set_uint32 + pws3_field_set_bytes + pws3_field_get_uuid + pws3_field_get_text + pws3_field_get_time + pws3_field_get_uint8 + pws3_field_get_uint16 + pws3_field_get_uint32 + pws3_field_get_bytes + pws3_record_create + pws3_record_destroy + pws3_record_set_field + pws3_record_get_field + pws3_record_remove_field + create and manipulate Password Safe File Version 3 + files + + + + cc + + + + + + + + + + + + + + + + + + +#include <pws.h> + + + struct pws3_file + *pws3_file_create + + + + void pws3_file_destroy + struct pws3_file + *pws_file + + + enum pws_error_code + pws3_file_get_error_code + struct pws3_file + *pws_file + + + const char * + pws3_file_get_error_message + struct pws3_file + *pws_file + + + int pws3_file_read_mem + struct pws3_file + *pws_file + const char + *password + unsigned char + *s + size_t + n + + + int pws3_file_read_stream + struct pws3_file + *pws_file + const char + *password + FILE + *fp + + + int pws3_file_write_mem + struct pws3_file + *pws_file + const char + *password + uint32_t + n_iter + unsigned char + **memp + size_t + *mem_sizep + + + int pws3_file_write_stream + struct pws3_file + *pws_file + const char + *password + uint32_t + n_iter + + + void pws3_file_set_header_field + struct pws3_file + *pws_file + struct pws3_field + *field + + + struct pws3_field * + pws3_file_get_header_field + struct pws3_file + *pws_file + uint8_t + field_type + + + struct pws3_field * + pws3_file_remove_header_field + struct pws3_file + *pws_file + uint8_t + field_type + + + void + pws3_file_insert_empty_group + struct pws3_file + *pws_file + struct pws3_field + *field + + + struct pws3_field * + pws3_file_get_empty_group + struct pws3_file + *pws_file + const char + *group_name + + + struct pws3_field * + pws3_file_remove_empty_group + struct pws3_file + *pws_file + const char + *group_name + + + struct pws3_field * + pws3_file_first_empty_group + struct pws3_file + *pws_file + + + struct pws3_field * + pws3_file_last_empty_group + struct pws3_file + *pws_file + + + struct pws3_field * + pws3_file_next_empty_group + struct pws3_file + *pws_file + struct pws3_field + *field + + + struct pws3_field * + pws3_file_prev_empty_group + struct pws3_file + *pws_file + struct pws3_field + *field + + + void pws3_file_insert_record + struct pws3_file + *pws_file + struct pws3_record + *record + + + struct pws3_record * + pws3_file_get_record + struct pws3_file + *pws_file + const unsigned char + uuid[static + PWS3_UUID_SIZE] + + + struct pws3_record * + pws3_file_remove_record + struct pws3_file + *pws_file + const unsigned char + uuid[static + PWS3_UUID_SIZE] + + + struct pws3_record * + pws3_file_first_record + struct pws3_file + *pws_file + + + struct pws3_record * + pws3_file_last_record + struct pws3_file + *pws_file + + + struct pws3_record * + pws3_file_next_record + struct pws3_file + *pws_file + struct pws3_record + *record + + + struct pws3_record * + pws3_file_prev_record + struct pws3_file + *pws_file + struct pws3_record + *record + + + struct pws3_field * + pws3_field_create + int + is_header + uint8_t + field_type + + + void pws3_field_destroy + struct pws3_field + *field + + + int + pws3_field_is_header + struct pws3_field + *field + + + uint8_t * + pws3_field_get_type + struct pws3_field + *field + + + enum pws_data_type * + pws3_field_get_data_type + struct pws3_field + *field + + + int pws3_field_set_uuid + struct pws3_field + *field + const unsigned char + uuid[static + PWS3_UUID_SIZE] + + + int pws3_field_set_text + struct pws3_field + *field + const char + s[static 1] + + + int pws3_field_set_time + struct pws3_field + *field + time_t + time + + + int pws3_field_set_uint8 + struct pws3_field + *field + uint8_t + u8 + + + int pws3_field_set_uint16 + struct pws3_field + *field + uint16_t + u16 + + + int pws3_field_set_uint32 + struct pws3_field + *field + uint32_t + u32 + + + int pws3_field_set_bytes + struct pws3_field + *field + const unsigned char + s[static 1] + size_t + n + + + const unsigned char * + pws3_field_get_uuid + struct pws3_field + *field + + + const char * + pws3_field_get_text + struct pws3_field + *field + + + time_t + pws3_field_get_time + struct pws3_field + *field + + + uint8_t + pws3_field_get_uint8 + struct pws3_field + *field + + + uint16_t + pws3_field_get_uint16 + struct pws3_field + *field + + + uint32_t + pws3_field_get_uint32 + struct pws3_field + *field + + + void pws3_field_get_bytes + struct pws3_field + *field + const unsigned char + **pp + size_t + *np + + + +PWS3_VERSION + +PWS3_MAX_FIELD_LEN + +PWS3_MAX_PASSWORD_LEN + +PWS3_UUID_SIZE + +struct pws3_field; + +struct pws3_record; + +struct pws3_file; + +enum pws_error_code; + +enum pws_data_type; + +enum pws3_header_field_type; + +enum pws3_record_field_type; + + + + Description + + Introduction + The pws3_*() family of functions allows + creating, reading, writing, and manipulating Password Safe version 3 + files. Password Safe version 3 files consist of a header and a body part. + The header is comprised of both mandatory and optional typed header + fields which hold file-wide metadata. The body consists of records which + in turn hold passwords and associated metadata in typed record + fields. + A header or record field value can be of one of seven basic data + types defined below: + + Header and Record Field Value Data Types + + + + Data Type + C Type + Description + + + + + PWS_DATA_TYPE_UUID + unsigned char [PWS3_UUID_SIZE] + UUID + + + PWS_DATA_TYPE_TEXT + char * + NUL-delimited UTF-8 encoded string + + + PWS_DATA_TYPE_TIME + time_t + system-specific representation of time + + + PWS_DATA_TYPE_UINT8 + uint8_t + 8-bit wide unsigned integer + + + PWS_DATA_TYPE_UINT16 + uint16_t + 16-bit wide unsigned integer + + + PWS_DATA_TYPE_UINT32 + uint32_t + 32-bit wide unsigned integer + + + PWS_DATA_TYPE_BYTES + unsigned char * + array of bytes + + + +
+
+ The data type of each header field is defined in + and the data type of each record + field is defined in . Each header + field, with the exception of the empty groups header field, can only + occur once. The version header field + (PWS3_HEADER_FIELD_VERSION) is mandatory and must + not be removed. When reading a file its value is checked and an error is + returned if the file format version newer than the one supported by + libpws3. + The supported version is defined by the PWS3_VERSION + macro, when creating a new file structure the version header field will be + set to its value by default. Non-standard header and record fields will + be preserved when a file is read and subsequently written again, they may + be read and manipulated as if they had + PWS_DATA_TYPE_BYTES data type. All strings are + expected to be in UTF-8 encoding. + The only mandatory record field is the UUID field which uniquely + identifies a record in the file. + The complete and authoritative specification of the file format is + included with the original Password Safe application available from . +
+ + Password Safe File Data Structure + The pws3_file_create() function allocates and + intializes a Password Safe file data structure representing a Password + Safe version 3 file. It automatically creates the mandatory version header + field and initializes it to the value of the + PWS3_VERSION macro. + The pws3_file_destroy() function deallocates + all header fields and records of the file structure passed to it and then + deallocates the file structure itself. + The pws3_file_read_mem() and + pws3_file_read_stream() functions read and parse a + Password Safe file into the given data structure passed via the + pws_file argument, replacing any existing header + fields and records. The key used to decrypt the file is derived from the + given password parameter. The + pws3_file_read_mem() function reads the file from a + block of memory s with the size of + n bytes. The + pws3_file_read_stream() reads the file from the + stream of the fp file pointer. + The pws3_file_write_mem() and + pws3_file_write_stream() functions write a new + Password Safe file from the given datat structure. The key used to + encrypt the file is derived from the password + argument using the number of iterations to stretch the key determined by + the n_iter argument. The + pws3_file_write_mem() will allocate and place the + file contents into memory and return the location and size to the + locations sp and np + point to. The pws3_file_write_stream() will write the + file contents to the stream of the fp file + pointer. + + + Fields + Both header and record fields are stored in + pws3_field structures which are allocated and + initialized with the pws3_field_create() function. + Depending on whether is_header is non-zero either + a header field or a record field data structure of the given field type + will be created. + The pws3_field_destroy() function + deallocates the given field data structure and its content. + The pws3_field_is_header() function + can be used to test whether the given field data structure refers to a + header field or a record field. + The pws3_field_get_type() function + returns the field type of the given field data structure. + The pws3_field_get_data_type() function + returns the data type of the given field structure. + The pws3_field_set_uuid(), + pws3_field_set_text(), + pws3_field_set_time(), + pws3_field_set_uint8(), + pws3_field_set_uint16(), + pws3_field_set_uint32(), and + pws3_field_set_bytes() functions set the + content of the given field. The given data is always copied and + existing content is replaced. The data type used by the function must + match the data type of the field specified in in case of header fields or that in in case of record fields. + The pws3_field_get_time(), + pws3_field_get_uint8(), + pws3_field_get_uint16(), and + pws3_field_get_uint32() functions return the + value of the given field. The + pws3_field_get_uuid(), + pws3_field_get_text(), and + pws3_field_get_bytes() functions return a + pointer to the data of the given field if it has been set. The data type + used by the function must match the data type of the field specified in + in case of header fields and that + in in case of record fields. + Returned pointers are only valid until a field is modified or + deallocated. + + + Header Fields + Header fields are used to store metadata for the whole file, each + type of header field with the exception of the empty groups header field + only occurs once. The following header fields are supported: + + Header Fields + + + + Header Field Type + Numeric Value + Data Type + Description + + + + + PWS3_​HEADER_​FIELD_​VERSION + 0x00 + PWS_​DATA_​TYPE_​UINT16 + file format version + + + PWS3_​HEADER_​FIELD_​UUID + 0x01 + PWS_​DATA_​TYPE_​UUID + UUID + + + PWS3_​HEADER_​FIELD_​NON_​DEFAULT_​PREFERENCES + 0x02 + PWS_​DATA_​TYPE_​TEXT + non-default preferences + + + PWS3_​HEADER_​FIELD_​TREE_​DISPLAY_​STATUS + 0x03 + PWS_​DATA_​TYPE_​TEXT + expandended/​collapsed state of the tree of groups + + + PWS3_​HEADER_​FIELD_​SAVE_​TIMESTAMP + 0x04 + PWS_​DATA_​TYPE_​TIME + time when the file was last saved + + + PWS3_​HEADER_​FIELD_​SAVE_​USER_​HOST + 0x05 + PWS_​DATA_​TYPE_​TEXT + name of the user who last saved the file and name of the host where the file was saved + + + PWS3_​HEADER_​FIELD_​SAVE_​APPLICATION + 0x06 + PWS_​DATA_​TYPE_​TEXT + name of the application used to save the file + + + PWS3_​HEADER_​FIELD_​SAVE_​USER + 0x07 + PWS_​DATA_​TYPE_​TEXT + name of the user who last saved the file + + + PWS3_​HEADER_​FIELD_​SAVE_​HOST + 0x08 + PWS_​DATA_​TYPE_​TEXT + name of the host where the file was last saved + + + PWS3_​HEADER_​FIELD_​DATABASE_​NAME + 0x09 + PWS_​DATA_​TYPE_​TEXT + logical name for referring to the file + + + PWS3_​HEADER_​FIELD_​DATABASE_​DESCRIPTION + 0x0a + PWS_​DATA_​TYPE_​TEXT + description of the file + + + PWS3_​HEADER_​FIELD_​DATABASE_​FILTERS + 0x0b + PWS_​DATA_​TYPE_​TEXT + filters for this file + + + PWS3_​HEADER_​FIELD_​RESERVED_​1 + 0x0c + PWS_​DATA_​TYPE_​BYTES + reserved + + + PWS3_​HEADER_​FIELD_​RESERVED_​2 + 0x0d + PWS_​DATA_​TYPE_​BYTES + reserved + + + PWS3_​HEADER_​FIELD_​RESERVED_​3 + 0x0e + PWS_​DATA_​TYPE_​BYTES + reseved + + + PWS3_​HEADER_​FIELD_​RECENTLY_​USED_​ENTRIES + 0x0f + PWS_​DATA_​TYPE_​TEXT + list of recently used entries + + + PWS3_​HEADER_​FIELD_​NAMED_​PASSWORD_​POLICIES + 0x10 + PWS_​DATA_​TYPE_​TEXT + named password policies + + + PWS3_​HEADER_​FIELD_​EMPTY_​GROUPS + 0x11 + PWS_​DATA_​TYPE_​TEXT + empty groups which contain no entries + + + PWS3_​HEADER_​FIELD_​YUBICO + 0x12 + PWS_​DATA_​TYPE_​TEXT + reserved + + + +
+
+ The pws3_file_set_header_field() function sets + the header field on the given file. An existing field of the same type is + replaced with the exception of fields of type + PWS3_HEADER_FIELD_EMPTY_GROUPS for which + pws3_file_set_header_field() has the same effect as + calling the pws3_file_insert_empty_group() + function. + The pws3_file_get_header_field() function + returns a pointer to the header field data structure of the given header + field type. In case of the + PWS3_HEADER_FIELD_EMPTY_GROUPS field type a pointer + to the first empty group field is returned. + The pws3_file_remove_header_field() function + removes the header field from the given file and returns a pointer to it. + It is the responsibility of the caller to deallocate the header field + data structure. In case of the + PWS3_HEADER_FIELD_EMPTY_GROUPS field type the first + empty group is removed. + The pws3_file_insert_empty_group() function + inserts the given empty groups field into the file, an existing field for + a group of the same name is replaced. + The pws3_file_get_empty_group() function + returns a pointer to the header field datat structure representing an + empty group of the given name. + The pws3_file_remove_empty_group() function + removes the field representing the empty group of the given name from the + file and returns a pointer to the header field data structure. It is the + responsibility of the caller to deallocate the header field data + structure. + The pws3_file_first_empty_group() function + returns a pointer to the first empty group header field. + The pws3_file_last_empty_group() function + returns a pointer to the last empty group header field. + The pws3_file_next_empty_group() function + returns a pointer to the next empty group header filed data structure + following the given field. + The pws3_file_prev_empty_groupious() function + returns a pointer to the previous empty group header filed data structure + preceding the given field. +
+ + Records + Records consist of at least one or more typed fields, they are + identified by an UUID which is the only mandatory field and must not be + removed. For presentational purposes records may be organized in + hierarchical groups. The following record fields are supported: + + Record Fields + + + + Record Field Type + Numeric Value + Data Type + Description + + + + + PWS3_​RECORD_​FIELD_​UUID + 0x01 + PWS_​DATA_​TYPE_​UUID + UUID identifying the record + + + PWS3_​RECORD_​FIELD_​GROUP + 0x02 + PWS_​DATA_​TYPE_​TEXT + group name the record is a member of + + + PWS3_​RECORD_​FIELD_​TITLE + 0x03 + PWS_​DATA_​TYPE_​TEXT + title + + + PWS3_​RECORD_​FIELD_​USERNAME + 0x04 + PWS_​DATA_​TYPE_​TEXT + username + + + PWS3_​RECORD_​FIELD_​NOTES + 0x05 + PWS_​DATA_​TYPE_​TEXT + notes + + + PWS3_​RECORD_​FIELD_​PASSWORD + 0x06 + PWS_​DATA_​TYPE_​TEXT + password + + + PWS3_​RECORD_​FIELD_​CREATION_​TIME + 0x07 + PWS_​DATA_​TYPE_​TIME + time when the record was created + + + PWS3_​RECORD_​FIELD_​PASSWORD_​MODIFICATION_​TIME + 0x08 + PWS_​DATA_​TYPE_​TIME + time when the password was last modified + + + PWS3_​RECORD_​FIELD_​ACCESS_​TIME + 0x09 + PWS_​DATA_​TYPE_​TIME + time when the record was last accessed + + + PWS3_​RECORD_​FIELD_​PASSWORD_​EXPIRY_​TIME + 0x0a + PWS_​DATA_​TYPE_​TIME + time when the password expires + + + PWS3_​RECORD_​FIELD_​RESERVED_​1 + 0x0b + PWS_​DATA_​TYPE_​BYTES + reserved + + + PWS3_​RECORD_​FIELD_​MODIFICATION_​TIME + 0x0c + PWS_​DATA_​TYPE_​TIME + time at whcih the record was last modified + + + PWS3_​RECORD_​FIELD_​URL + 0x0d + PWS_​DATA_​TYPE_​TEXT + URL + + + PWS3_​RECORD_​FIELD_​AUTOTYPE + 0x0e + PWS_​DATA_​TYPE_​TEXT + text to be typed when using the autotype feature + + + PWS3_​RECORD_​FIELD_​PASSWORD_​HISTORY + 0x0f + PWS_​DATA_​TYPE_​TEXT + creation time and values of previously used passwords + + + PWS3_​RECORD_​FIELD_​PASSWORD_​POLICY + 0x10 + PWS_​DATA_​TYPE_​TEXT + password policy + + + PWS3_​RECORD_​FIELD_​PASSWORD_​EXPIRY_​INTERVAL + 0x11 + PWS_​DATA_​TYPE_​UINT32 + days until the password expires + + + PWS3_​RECORD_​FIELD_​RUN_​COMMAND + 0x12 + PWS_​DATA_​TYPE_​TEXT + command + + + PWS3_​RECORD_​FIELD_​DOUBLE_​CLICK_​ACTION + 0x13 + PWS_​DATA_​TYPE_​BYTES + action on double clicking + + + PWS3_​RECORD_​FIELD_​EMAIL_​ADDRESS + 0x14 + PWS_​DATA_​TYPE_​TEXT + email address + + + PWS3_​RECORD_​FIELD_​PROTECTED + 0x15 + PWS_​DATA_​TYPE_​UINT8 + flag whether the record is protected from modification + + + PWS3_​RECORD_​FIELD_​ALLOWED_​PASSWORD_​SYMBOLS + 0x16 + PWS_​DATA_​TYPE_​TEXT + allowed symbols for generating passwords + + + PWS3_​RECORD_​FIELD_​SHIFT_​DOUBLE_​CLICK_​ACTION + 0x17 + PWS_​DATA_​TYPE_​BYTES + action on pressing shift and double clicking + + + PWS3_​RECORD_​FIELD_​PASSWORD_​POLICY_​NAME + 0x18 + PWS_​DATA_​TYPE_​TEXT + name of password policy saved in the header + + + PWS3_​RECORD_​FIELD_​KEYBOARD_​SHORTCUT + 0x19 + PWS_​DATA_​TYPE_​BYTES + keyboard shortcut + + + +
+
+ The pws3_record_create() function allocates + and creates a record data structure, generates an UUID record field and + adds it to the record. + The pws3_record_destroy() function deallocates + the given record data structure and all its record fields. + The pws3_file_record_field_set() function sets + the record field on the given record, replacing an existing field of the + same type. + The pws3_file_record_field_get() function + returns a pointer to the record field data structure of the given record + field type. + The pws3_file_record_field_remove() function + removes the record field from the given record and returns a pointer to + it. It is the responsibility of the caller to deallocate the record field + data structure. + The pws3_file_insert_record() function inserts + the given record into the file, an existing record with the same UUID is + replaced. + The pws3_file_get_record() function returns a + pointer to the record structure representing a record with the given + UUID. + The pws3_file_remove_record() function removes + the record with the given UUID from the file and returns a pointer to the + record data structure. It is the responsibility of the caller to + deallocate the record data structure. + The pws3_file_first_record() function returns a + pointer to the first record. + The pws3_file_last_record() function returns a + pointer to the last record. + The pws3_file_next_record() function returns a + pointer to the next record following the given + record. + The pws3_file_prev_record() + function returns a pointer to the previous group preceding the given + record. +
+ + Macros + The macro PWS3_VERSION contains the supported + version of the Password Safe version 3 file format. + The macro PWS3_MAX_FIELD_SIZE contains the + maxium size for header and record fields in bytes and + PWS3_MAX_PASSWORD_LEN contains the maxium password + length in bytes. + The macro PWS3_UUID_SIZE contains the size of + UUIDs in bytes. + +
+ + Return Values + The pws3_file_create() function returns a + pointer to a Password Safe file data structure if successful and + NULL in case of an error. + The pws3_file_read_mem(), + pws3_file_read_stream(), + pws3_file_write_mem(), and + pws3_file_write_stream() functions return + 0 on success and -1 + to indicate an error. + The pws3_file_get_header_field() function + returns a pointer to the header field data structure of the requested type + and NULL if such a field does not exist. + The pws3_file_remove_header_field() function + returns a pointer to the header field data structure which was removed from + the file or NULL if such a field does not exist. + The pws3_file_get_empty_group() function returns + a pointer to the header field data structure corresponding to the requested + empty group and NULL if a group of that name does not + exist. + The pws3_file_remove_empty_group() function + returns a pointer to the header field data structure of the empty group + which was removed from the file or NULL if a group of + that name does not exist. + The pws3_file_first_empty_group() function + returns a pointer to the first of the empty group header fields or + NULL if there are no such fields. + The pws3_file_last_empty_group() function + returns a pointer to the last of the empty group header fields or + NULL if there are no such fields. + The pws3_file_next_empty_group() function + returns a pointer to the next empty group header field or + NULL if there are no more such fields. + The pws3_file_prev_empty_group() function + returns a pointer to the previous empty group header field or + NULL if there are no more such fields. + The pws3_file_get_record() function returns a + pointer to the record data structure of the requested record or + NULL if that record does not exist. + The pws3_file_remove_record() function returns a + pointer to the record data structure which was removed from the file or + NULL if no such record exists. + The pws3_file_first_record() function returns a + pointer to the record data structure of the first record or + NULL if no records exist. + The pws3_file_last_record() function returns a + pointer to the record data structure of the last record or + NULL if no records exist. + The pws3_file_next_record() function returns a + pointer to the record data structure of the next record or + NULL if no records exist. + The pws3_file_prev_record() function returns a + pointer to the record data structure of the previous record or + NULL if no records exist. + The pws3_field_create() function returns a + pointer to the new header field data structure on success and + NULL on failure. + The pws3_field_get_type() function returns + the field type of the header field structure. + The pws3_field_get_data_type() function + returns the data type of the header field structure. + The pws3_field_set_uuid(), + pws3_field_set_text(), + pws3_field_set_time(), + pws3_field_set_uint8(), + pws3_field_set_uint16(), + pws3_field_set_uint32(), and + pws3_field_set_bytes() functions return + 0 on success and -1 + on failure. + The pws3_field_get_time(), + pws3_field_get_uint8(), + pws3_field_get_uint16(), and + pws3_field_get_uint32() functions return a + value of the type corresponding to the type of header field. + The pws3_field_get_uuid() function + returns a pointer to a UUID. + The pws3_field_get_text() function + returns a pointer to a string or NULL if no value has + been set. + The pws3_record_create() function returns a + pointer to a record data structure if successful and + NULL on failure. + The pws3_record_get_field() function returns a + pointer to the record field data structure of the requested type or + NULL if such a field does not exist. + The pws3_record_remove_field() function returns + a pointer to the record field data structure which was removed from the + record or NULL if such a field does not exist. + + + Errors + If the pws3_file_read_mem(), + pws3_file_read_stream(), + pws3_file_write_mem(), and + pws3_file_write_stream() functions fail, an error code + indicating the nature of the error may be obtained using the + pws3_file_get_error_code() function and a pointer to a + detailed error message may be retrieved using the + pws3_file_get_error_message() function. The above + functions may fail if: + + + PWS_ERR_GENERIC_ERROR + + An unknown error occurred. + + + + PWS_ERR_NO_MEMORY + + There was not enough space to allocate memory. + + + + PWS_ERR_IO_ERROR + + An I/O error occurred. + + + + PWS_ERR_TRUNCATED_FILE + + The file appears to be truncated. + + + + PWS_ERR_INVALID_CHECKSUM + + The calculated checksum does not match the checksum of the + file. + + + + PWS_ERR_INVALID_RECORD + + A record is invalid. + + + + PWS_ERR_INVALID_HEADER + + A header is invalid. + + + + PWS_ERR_UNSUPPORTED_VERSION + + The file format version is not supported. + + + + + + Examples + + Creating a Password Safe file + The following code creates a new Password Safe file and sets the + save application header field: + + + +/* ... */ + +struct pws3_file *file; +struct pws3_field *application_field; + +/* ... */ + +/* initialize libpws */ +if (pws_init() != 0) { + /* handle error */ +} + +/* ... */ + +/* create a new empty file structure */ +file = pws3_file_create(); +if (file == NULL) { + /* handle error */ +} +/* create new empty save application field */ +application_field = pws3_field_create(1, PWS3_HEADER_FIELD_SAVE_APPLICATION); +if (application_field == NULL) { + /* handle error */ +} +/* set the value of the field */ +if (pws3_field_set_text(application_field, "PasswordManager 2.0") != 0) { + /* handle error */ +} +/* set the header save application field in the file to the new field */ +pws3_file_set_field(file, application_field); +]]> + + + + Print the title of each record + The following code loops over each record of an existing Password + Safe file and prints the content of the title field if it exists: + + +#include + +/* ... */ + +struct pws3_file *file; +struct pws3_record *record; +struct pws3_field *title_field; + +/* ... */ + +/* interate over each record */ +for (record = pws3_file_first_record(file); record != NULL; + record = pws3_file_next_record(file, record)) { + /* retrieve title field */ + title_field = pws3_record_get_field(record, PWS3_RECORD_FIELD_TITLE); + /* print the title field or "No title" if it does not exitst */ + printf("Title: %s\n", (title_field != NULL) ? + pws3_record_field_get_text(PWS3_RECORD_FIELD_TITLE) : "No title"); +} +]]> + + + + Add a new record to a file + The following code creates a new record with a password field, a + title field, and a creation time field and adds it to an existing + Password Safe file: + + +#include + +/* ... */ + +struct pws3_file *file; +struct pws3_record *record; +struct pws3_field *password_field; +struct pws3_field *title_field; +struct pws3_field *ctime_field; +time_t now; + +/* ... */ + +/* create new record */ +record = pws3_record_create(); +if (record == NULL) { + /* handle error */ +} + +/* create a password field */ +password_field = pws3_record_field_create(PWS3_RECORD_FIELD_PASSWORD); +if (password_field == NULL) { + /* handle error */ +} +/* set the value of the password field to "PaSsWoRd" */ +if (pws3_record_field_set_text(password_field, "PaSsWoRd") != 0) { + /* handle error */ +} +/* set the password field of the record to the new field */ +pws3_record_set_field(record, password_field); + +/* create a title field */ +title_field = pws3_record_field_create(PWS3_RECORD_FIELD_TITLE); +if (title_field == NULL) { + /* handle error */ +} +/* set the value of the title field to "Foo Bar" */ +if (pws3_record_field_set_text(title_field, "Foo Bar") != 0) { + /* handle error */ +} +/* set the title field of the record to the new field */ +pws3_record_set_field(record, title_field); + +/* create a new creation time field */ +ctime_field = pws3_record_field_create(PWS3_RECORD_FIELD_CREATION_TIME); +if (ctime_field == NULL) { + /* handle error */ +} +/* set the value of the creation time field to the current time */ +pws3_record_field_set_time(ctime_field, time(NULL)); +/* set the creation time field of the record to the new field */ +pws3_record_set_field(record, ctime_field); + +/* insert the new record into the file */ +pws3_file_insert_record(file, record); +]]> + + + + Reading a Password Safe file + The following code opens a Password Safe file named + example.pwsafe3 and parses it: + + +#include + +/* ... */ + +FILE *fp; +struct pws3_file *file; + +/* ... */ + +/* initialize libpws */ +if (pws_init() != 0) { + /* handle error */ +} + +/* ... */ + +/* create a new empty file structure */ +file = pws3_file_create(); +if (file == NULL) { + /* handle error */ +} + +/* open the file */ +fp = fopen("example.pwsafe3", "r"); +if (fp == NULL) { + /* handle error */ +} + +/* read and parse the file contents into the file structure */ +if (pws3_file_read_stream(file, "PaSsWoRd", fp) != 0) { + fprintf(stderr, "error: %s\n", + pws3_file_get_error_message(file)); + /* handle error */ +} +]]> + + + + Writing a Password Safe file + The following code writes a Password Safe file to a file + named example.pwsafe3: + + +#include + +/* ... */ + +FILE *fp; +struct pws3_file *file; + +/* ... */ + +fp = fopen("example.pwsafe3", "w"); +if (fp == NULL) { + /* handle error */ +} + +if (pws3_file_write_stream(file, "FoOBaR", 10000, fp) != 0) { + /* handle error */ +} + +fflush(fp); +fclose(fp); +]]> + + + + + See Also + libpws + 3, + pws_init + 3, + + +
diff -r d541e748cfd8 -r e1309515d111 pws_init.3.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pws_init.3.xml Wed Mar 25 17:10:23 2015 +0100 @@ -0,0 +1,159 @@ + + + + + + + Guido + Berhoerster + + guido+libpws@berhoerster.name + + + 21 March, 2015 + + + libpws + 3 + + + Library Functions + + + pws_init + pws_finalize + pws_set_alloc_functions + pws_generate_uuid + initalize and deinitialize libpws + + + + cc + + + + + + + + + + + + + + + + + + +#include <pws.h> + + + int pws_init + + + + void pws_finalize + + + + void pws_set_alloc_functions + void + **alloc_functionsize_t + void + **realloc_functionvoid *, size_t + void *free_functionvoid + *, size_t + void + **secure_alloc_functionsize_t + void + **secure_realloc_functionvoid *, size_t + void *secure_free_functionvoid + *, size_t + + + int pws_generate_uuid + unsigned char [static PWS3_UUID_SIZE] + + + +LIBPWS_VERSION_MAJOR + +LIBPWS_VERSION_MINOR + +LIBPWS_VERSION_MICRO + + + + Description + The pws_init() function initializes + libpws3 + and must be called before any other function from this library. + The pws_finalize() function deinitializes + libpws3 + after which no other function from this library may be called. + The pws_set_alloc_functions() function specifies + the functions which are used by + libpws3 + to allocate, reallocate or free memory allowing for the use of custom + allocators. pws_secure_alloc, + pws_secure_realloc, and + pws_secure_free are used to allocate, reallocate, and + free memory containing potentially sensitive information such as passwords, + this e.g. allows for wrapping the acutal allocation using operating system + specific facilities to prevent memory from being paged to the swap area or + to overwrite memory before deallocating it. Any argument set to + NULL will result in the default function being used, + these are malloc, realloc, and a + wrapper around free. This function must be called + after pws_init and before calling any other function + from this library. It is not reentrant. + The pws_uuid_create() function generates a new + random UUID following RFC4122 and places it in the array passed to + it. + The macros LIBPWS_VERSION_MAJOR, + LIBPWS_VERSION_MINOR, and + LIBPWS_VERSION_MICRO can be used to check the major, + minor, and micro version of the library. + + + Return Values + The pws_init() function returns + 0 if the library was initialized successfully and + -1 on failure. + The pws_generate_uuid() returns + 0 if a new random UUID has been generated and + -1 on failure. + + + See Also + libpws + 3, + pws3_file_create + 3, RFC4122 + +