     [file version.texi not included]

This file documents the use and the internals of Assuan.

This is Edition EDITION, last updated UPDATED, of The `Developing with Assuan' Manual, for Version VERSION.

Published by the Free Software Foundation

51 Franklin Street, Fifth Floor

Boston, MA 02110-1301 USA

Copyright © 2002, 2003, 2006, 2007 Free Software Foundation, Inc.

Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version. The text of the license can be found in the
section entitled ``Copying''.

Introduction
************

This manual documents how to exploit the Assuan library, a simple interprocess communcation library.

Introduction to Assuan
**********************

In an ideal world, Assuan would not be necessary.  Assuan's primary use is to allow a client to interact with a non-persistent server. Using Assuan, this is accomplished by forking a subprocess and communicating with it via, for example, a pipe or Unix domain socket. This method is neither elegant nor efficient, especially when there is a lot of data spread across several transactions: not only is there a penalty for an increased number of context switches, but also a significant amount of data is MEMCPYed from the client to a file descriptor and from the file descriptor to the server.  Despite these and other disadvantages, this type of client/server communication can be useful: the client is completely separate from the server; they are in different address spaces.  This is especially important in situations where the server must have a known degree of reliability and data must be protected: as the Assuan protocol is well defined and clients cannot corrupt the servers' address space, auditing becomes much easier.

Assuan was developed for use by the GNU Privacy Guard, GnuPG, to prevent potentially buggy clients from unwittingly corrupting sensitive transactions or compromising data such as a secret key. Assuan permits the servers, which do the actual work, e.g. encryption and decryption of data using a secret key, to be developed independently of the user interfaces, e.g. mail clients and other encryption front ends.  Like a shared library, the interface is well defined and any number of front ends can use it; however, unlike a shared library, the client cannot see or touch the server's data.  As with any modular system, Assuan helps keep the components small, understandable and less error prone.

Assuan is not, however, limited to use with GnuPG servers and clients: it was designed to be flexible enough to meet the demands of many transaction based environments with non-persistent servers.

Description of the Assuan protocol.
***********************************

The architecture of the modular GnuPG system is based on several highly specialized modules which compose a network of client/server communication.  A common framework for intermodule communication is therefore needed and should be implemented in a library.

Goals:

  * Common framework for module communication

  * Easy debugging

  * Easy module testing

  * Extendible

  * Optional authentication and encryption facility

  * Usable to access external hardware

Design criteria:

  * Client server with back channel

  * Use a mainly text based protocol

  * Escape certain control characters

  * Allow indefinite data length

  * Request confidentiality for parts of the communication

  * Dummy module to allow direct linking of client and server

  * Inline data or descriptor passing for bulk data

  * No protection against DoS needed

  * Subliminal channels are not an issue

Implementation
**************

The implementation is line based with a maximum line size of 1000 octets.  The default IPC mechanism are Unix Domain Sockets.

On a connect request the server responds either with an okay or an error status.  For authentication check the server may send an Inquiry Response prior to the first Okay, and it may also issue Status messages.  The server must check that the client is allowed to connect, this is done by requesting the credentials for the peer and comparing them to those of the server.  This avoids attacks based on wrong socket permissions.

It may choose to delay the first response in case of an error.  The server never closes the connection - however the lower protocol may do so after some time of inactivity or when the connection is in an error state.

All textual messages are assumed to be in UTF-8 unless otherwise noted.

Server responses
================

OK  [<arbitrary debugging information>]
     Request was successful.

ERR ERRORCODE [<human readable error description>]
     Request could not be fulfilled.  The error codes are mostly application specific except for a few common ones.

S KEYWORD <status information depending on keyword>
     Informational output by the server, still processing the request.

# <string>
     Comment line issued only for debugging purposes.  Totally ignored.

D <raw data>
     Raw data returned to client. There must be exactly one space after the 'D'.  The values for '%', CR and LF must be percent escaped; this is encoded as %25, %0D and %0A.  Only uppercase letters should be used in the hexadecimal representation.  Other characters may be percent escaped for easier debugging.  All these Data lines are considered one data stream up to the OK or ERR response.  Status and Inquiry Responses may be mixed with the Data lines.

INQUIRE KEYWORD <parameters>
     Server needs further information from the client.  The client should answer with a command which is allowed after an inquiry.  Note that the server does not confirm that client command but either continues processing or ends processing with an error status.  Not all commands are allowed.

A client should only check the first letter of each line and then skip over to the next token (except for data lines where the raw data starts exactly after 2 bytes).  Lines larger than 1000 bytes should be treated as a communication error. (The rationale for having a line length limit is to allow for easier multiplexing of several channels).

Client requests
===============

The server waits for client requests after he sent an Okay or Error. The client should not issue a request in other cases.

     COMMAND <parameters>

COMMAND is a one word string without preceding white space. Parameters are command specific, CR, LF and the percent signs should be percent escaped as described above.  To send a backslash as the last character it should also be percent escaped.  Percent escaping is allowed anywhere in the parameters but not in the command.  The line ends with a CR, LF or just a LF.

Not yet implemented feature: If there is a need for a parameter list longer than the line length limit (1000 characters including command and CR, LF), the last character of the line (right before the CR/LF or LF) must be a non-escape encoded backslash. The following line is then expected to be a continuation of the line with the backslash replaced by a blank and the line ending removed.

     D <raw data>

Raw data to the server. There must be exactly one space after the 'D'. The values for '%', CR and LF must be percent escaped; this is encoded as %25, %0D and %0A.  Only uppercase letters should be used in the hexadecimal representation.  Other characters may be percent escaped for easier debugging.  All these Data lines are considered one data stream up to the OKAY or ERROR response.  Status and Inquiry Responses may be mixed with the Data lines.

     END

Lines beginning with a # or empty lines are ignored.  This is useful to comment test scripts.

Although the commands are application specific, some of them are used by all protocols and partly directly supported by the Assuan library:

BYE
     Close the connect, the server will reply with an OK.

RESET
     Reset the connection but not any existing authentication.  The server should release all resources associated with the connection.

END
     Used by a client to mark the end of raw data.  The server may send END to indicate a partial end of data.

HELP
     Reserved for future extensions.

QUIT
     Reserved for future extensions.

OPTION
     Set options for the connection.  The syntax of such a line is

            OPTION NAME [ [=] VALUE ]

     Leading and trailing spaces around NAME and VALUE are allowed but should be ignored.  For compatibility reasons, NAME may be prefixed with two dashes.  The use of the equal sign is optional but suggested if VALUE is given.

CANCEL
     This command is reserved for future extensions.

AUTH
     This command is reserved for future extensions.  Not yet specified as we don't implement it in the first phase.  See my mail to gpa-dev on 2001-10-25 about the rationale for measurements against local attacks.

Error codes
===========

In general Libassuan should be used with gpg-error style error codes. For compatibility reasons and for applications not wanting to use these error codes, the old Assuan error codes may still be used.  In fact they are used by default.  To switch to gpg-error style error codes, applications should call the function assuan_set_assuan_err_source right after startup.

Preparation
***********

To use `LIBASSUAN', you have to perform some changes to your sources and the build system.  The necessary changes are small and explained in the following sections.

Header
======

All interfaces (data types and functions) of LIBASSUAN are defined in the header file assuan.h.  You must include this in all source files using the library, either directly or through some other header file, like this:

     #include <assuan.h>

The name space of `ASSUAN' is assuan_* for function and type names and ASSUAN* for other symbols.  In addition the same name prefixes with one prepended underscore are reserved for internal use and should never be used by an application.

Building sources
================

If you want to compile a source file including the assuan.h header file, you must make sure that the compiler can find it in the directory hierarchy.  This is accomplished by adding the path to the directory in which the header file is located to the compilers include file search path (via the -I option).

However, the path to the include file is determined at the time the source is configured.  To solve this problem, LIBGCRYPT ships with a small helper program libassuan-config that knows the path to the include file and other configuration options.  The options that need to be added to the compiler invocation at compile time are output by the --cflags option to libassuan-config.  The following example shows how it can be used at the command line:

     gcc -c foo.c $(libassuan-config --cflags)

Adding the output of libassuan-config --cflags to the compiler's command line will ensure that the compiler can find the assuan.h header file.

A similar problem occurs when linking the program with the library. Again, the compiler/linker has to find the library files.  For this to work, the path to the library files has to be added to the library search path (via the -L option).  For this, the option --libs to libassuan-config can be used.  For convenience, this option also outputs all other options that are required to link the program with the LIBASSUAN libraries (in particular, the -lassuan option).  The example shows how to link foo.o with the LIBASSUAN library to a program foo.

     gcc -o foo foo.o $(libassuan-config --libs)

Of course you can also combine both examples to a single command by specifying both options to libassuan-config:

     gcc -o foo foo.c $(libassuan-config --cflags --libs)

If your application uses Pth or pthread, you need to pass the option --thread=pth respective --thread=pthread to the invocation of libassuan-config.

Building sources using Automake
===============================

It is much easier if you use GNU Automake instead of writing your own Makefiles.  If you do that you do not have to worry about finding and invoking the libassuan-config script at all.  LIBASSUAN provides an Automake macro that does all the work for you.

 -- Macro: AM_PATH_LIBASSUAN ([minimum-version], [action-if-found], [action-if-not-found])
     Check whether LIBASSUAN (at least version MINIMUM-VERSION, if given) exists on the host system.  If it is found, execute ACTION-IF-FOUND, otherwise do ACTION-IF-NOT-FOUND, if given.

     Additionally, the function defines LIBASSUAN_CFLAGS to the flags needed for compilation of the program to find the assuan.h header file, and LIBASSUAN_LIBS to the linker flags needed to link the program to the LIBASSUAN library.

You can use the defined Autoconf variables like this in your Makefile.am:

     AM_CPPFLAGS = $(LIBASSUAN_CFLAGS)
     LDADD = $(LIBASSUAN_LIBS)

 -- Macro: AM_PATH_LIBASSUAN_PTH ([minimum-version], [action-if-found], [action-if-not-found])
     Same as AM_PATH_LIBASSUAN but checks for the GNU Pth enabled version of the library and defines LIBASSUAN_PTH_CFLAGS LIBASSUAN_PTH_LIBS instead.  Use this is you are using GNU Pth. Note that you also need to pass the appropriate options for Pth to the compiler and linker.

 -- Macro: AM_PATH_LIBASSUAN_PTHREAD ([minimum-version], [action-if-found], [action-if-not-found])
     Same as AM_PATH_LIBASSUAN but checks for the pthreads enabled version of the library and defines LIBASSUAN_PTHREAD_CFLAGS LIBASSUAN_PTHREAD_LIBS instead.  Use this is you are using GNU Pth. Note that you also need to pass the appropriate options for Pth to the compiler and linker.

Multi Threading
===============

The LIBGCRYPT library is thread-safe if you adhere to the following requirements:

  * Run the initialization functions before you actually start to use threads.

  * Only one thread at a time may access an LIBASSUAN context.

  * Use assuan_set_assuan_log_stream to setup a default log stream.

Generalities
************

Data Types used by the library
==============================

LIBASSUAN uses a context approach to keep state.  The following data type is used all over the place:

 -- Data type: assuan_context_t
     The assuan_context_t type is a pointer to an object maintained internally by the library.  Certain Assuan functions allocate such a context and return it to the caller using this data type. Other functions take this data type to access the state created by these functions.

For compatibility with older versions of LIBASSUAN a data type for error return values exists:

 -- Data type: assuan_error_t
     This has originally been an enum but applications should either view it as an int or if possible use the gpg_error_t data type as defined by the LIBGPG-ERROR package.

Initializing the library
========================

In general the library requires no initialization.  There are however some initialization hooks provided which are often useful.  These should be called as early as possible and in a multi-threaded application before a second thread is created.

If your application uses its own memory allocation functions or wrappers it is good idea to tell LIBASSUAN about it so it can make use of the same functions or wrappers.  You do this with

 -- Function: void assuan_set_malloc_hooks (void *(*MALLOC_FUNC)(size_t), void *(*REALLOC_FUNC)(void *, size_t), void (*FREE_FUNC)(void*))
     You need to provide all three functions.  Those functions need to behave exactly as their standard counterparts (malloc, realloc and free).  If you write your own functions please take care to set errno whenever an error has occurred.

To integrate assuan logging and diagnostics into your own logging system, you may use the following two functions:

 -- Function: void assuan_set_assuan_log_stream (FILE *FP)
     This sets the stream to which LIBASSUAN should log messages not associated with a specific context to FP.  The default is to log to stderr.  This default value is also changed by using assuan_set_log_stream (to set a logging stream for a specific context) unless this function has been used.  Obviously this is not thread-safe and thus it is highly recommended to use this function to setup a proper default.

 -- Function: void assuan_set_assuan_log_prefix (const char *TEXT)
     Set the prefix to be used at the start of a line emitted by assuan on the log stream to TEXT.  The default is the empty string.

If you intend to use LIBASSUAN along with the package LIBGPG-ERROR it is recommended to switch LIBASSUAN into a mode which directly makes use of error codes provided by LIBGPG-ERROR. Because the Assuan error codes and those of gpg-error overlap, it is required to explicitly request this.  You do this by calling the function

 -- Function: void assuan_set_assuan_err_source (int ERRSOURCE)
     Enable gpg-error style error codes.  ERRSOURCE is one of the gpg-error sources.  Switching back to the old style mode is not possible.  The usual way to call this function is

          assuan_set_assuan_err_source (GPG_ERR_SOURCE_DEFAULT);

How to communicate with the peer
================================

What would be an IPC library without the ability to read and write data?  Not very useful.  Libassuan has high level functions to take care of of the more boring stuff but eventually data needs to be written and read.

The basic read and write functions are:

 -- Function: assuan_error_t assuan_read_line (assuan_context_t CTX, char **LINE, size_t *LINELEN)

     Read the next line from the client or server and store a pointer to the buffer holding that line at the address LINE.  The valid length of the lines is stored at the address of LINELEN. This buffer is valid until the next read operation on the same context CTX.  You may modify the context of this buffer.  The buffer is invalid (i.e. must not be used) if an error is returned.  This function returns 0 on success or an error code.

 -- Function: assuan_error_t assuan_write_line (assuan_context_t CTX, const char *LINE)

     Write the string LINE to the other end.  This string needs to be a proper formatted Assuan protocol line and should not include a linefeed. Sending linefeed or Nul characters is not possible and not allowed by the assuan protocol.  This function shall not be used for sending data (D) lines.  This function returns 0 on success or an error code.

To actually send bulk data lines a specialized function is available:

 -- Function: assuan_error_t assuan_send_data (assuan_context_t CTX, const void *BUFFER, size_t LENGTH)

     This function is used by a server or a client to send LENGTH bytes of bulk data in BUFFER to the other end. The data will be escaped as required by the Assuan protocol and may get buffered until a line is full.  To force sending the data out BUFFER may be passed as NULL and LENGTH be 0.

     When used by a client this flush operation does also send the terminating END command to terminate the response on an ``INQUIRE'' response.  Note that the function assuan_transact takes care of sending this END itself.

     This function returns 0 on success or an error code.

How to develop an Assuan client
*******************************

Depending on the type of the server you want to connect you need to use different functions.

For a pipe based server you fork and exec yourself, you use:

 -- Function: assuan_error_t assuan_pipe_connect (assuan_context_t *CTX,const char *NAME, const char *const ARGV[], int *FD_CHILD_LIST)

     A call to this functions forks the current process and executes the program NAME, passing the arguments given in the NULL-terminated list ARGV.  A list of file descriptors not to be closed may be given using the -1 terminated array FD_CHILD_LIST.

     On success a new assuan context is returned at CTX.

If it is not a simple pipe server but one using full-duplex sockets, the full-fledged variant of the above function should be used:

 -- Function: assuan_error_t assuan_pipe_connect_ext (assuan_context_t *CTX,const char *NAME, const char *const ARGV[], int *FD_CHILD_LIST, void (*ATFORK) (void *, int), void *ATFORKVALUE, unsigned int FLAGS)

     A call to this functions forks the current process and executes the program NAME, passing the arguments given in the NULL-terminated list ARGV.  A list of file descriptors not to be closed may be given using the -1 terminated array FD_CHILD_LIST.

     If NAME as well as ARGV are given as NULL, only a fork but no exec is done.  Thus the child continues to run.  However all file descriptors are closed and some special environment variables are set. To let the caller detect whether the child or the parent continues, the child returns with a CTX set to NULL.

     If ATFORK is not NULL, this function is called in the child right after the fork and the value ATFORKVALUE is passed as the first argument.  That function should only act if the second argument it received is 0.  Such a fork callback is useful to release additional resources not to be used by the child.

     FLAGS controls how the function acts: With a value of 0 it expects a simple pipe based server and behaves similar to assuan_pipe_connect.  With a value of 1 a sever based on full-duplex pipes is expected.  Such pipes are usually created using the socketpair function.  It also enables features only available with such servers.

If you are using a long running server listening either on a TCP or a Unix domain socket, the following function is used to connect to the server:

 -- Function: assuan_error_t assuan_socket_connect_ext (assuan_context_t *CTX, const char *NAME, pid_t SERVER_PID, unsigned int FLAGS)

     Make a connection to the Unix domain socket NAME and return a new Assuan context at CTX.  SERVER_PID is currently not used but may become handy in the future; if you don't know the server's pid, pass -1.  With FLAGS set to 1, sendmsg and recvmesg are used for input and output and thereby enabling the the use of descriptor passing.

     Connecting to a TCP server is not yet implemented.  Standard URL schemes are reserved for NAME specifying a TCP server.

 -- Function: assuan_error_t assuan_socket_connect (assuan_context_t *CTX, const char *NAME, pid_t SERVER_PID)

     Same as above but no way to specify flags.

Finally, after using the Assuan connection, the resources should be deallocated:

 -- Function: void assuan_disconnect (assuan_context_t CTX)

     Close the connection described by the Assuan context CTX and release all resources.  This function also tries to send the BYE command to the server but won't fail on error. It is explicitly allowed to pass NULL for CTX, in which case the function does nothing.

Now that we have a connection to the server, all work may be conveniently done using a couple of callbacks and the transact function:

 -- Function: assuan_error_t assuan_transact (assuan_context_t CTX, const char *COMMAND, int (*DATA_CB)(void *, const void *, size_t), void *DATA_CB_ARG, int (*INQUIRE_CB)(void*, const char *), void *INQUIRE_CB_ARG, int (*STATUS_CB)(void*, const char *), void *STATUS_CB_ARG)

     Here CTX is the Assuan context opened by one of the connect calls.  COMMAND is the actual one liner Assuan command.  It shall not end with a line feed and its length is limited to ASSUAN_LINELENGTH (~1000 bytes)

     DATA_CB is called by Libassuan for data lines; DATA_CB_ARG is passed to it along with the data and the length.  [FIXME: needs more documentation].

     INQUIRE_CB is called by Libassuan when the server requests additional information from the client while processing the command. This callback shall check the provided inquiry name and send the data as requested back using the assuan_write_data.  The server passed INQUIRY_CB_ARG along with the inquiry name to the callback.

     STATUS_CB is called by Libassuan for each status line it receives from the server. STATUS_CB_ARG is passed along with the status line to the callback.

     The function returns 0 success or an error code.  The error code may be the one one returned by the server in error lines or one generated by the callback functions.

Libassuan supports descriptor passing on some platforms.  The next two functions are used with this feature:

 -- Function: assuan_error_t assuan_sendfd (assuan_context_t CTX, int FD)

     Send the descriptor FD to the peer using the context CTX. Note, that calling this function with a CTX of NULL and FD of -1 is a valid runtime test to check whether descriptor passing is available on the platform.  The descriptor must be sent before the command is issued that makes use of the descriptor.

 -- Function: assuan_error_t assuan_receivefd (assuan_context_t CTX, int *FD)

     Receive a descriptor pending for the context CTX from the peer. The descriptor must be pending before this function is called.  To accomplish this, the peer needs to use assuan_sendfd before the trigger is sent (e.g. using assuan_write_line ("INPUT FD").

How to develop an Assuan server
*******************************

Implementing a server for Assuan is a bit more complex than a client. However it is a straightforward task we are going to explain using a commented example.

The list of the implemented server commands is defined by a table like:

       static struct {
         const char *name;
         int (*handler)(assuan_context_t, char *line);
       } command_table[] = {
         { "FOO",          cmd_foo },
         { "BAR",          cmd_bar },
         { "INPUT",        NULL    },
         { "OUTPUT",       NULL    },
         { NULL                    }};

For convenience this table is usually put after the actual command handlers (cmd_foo, cmd_bar) or even put inside the command_handler. Note that commands with the name ``INPUT'' and ``OUTPUT'' do not require a handler because Libassuan provides a default handler for them.  It is however possible to assign a custom handler.

A prerequisite for this example code is that a client has already connected to the server.  Often there are two modes combined in one program: A pipe based server, where a client has forked the server process, or a Unix domain socket based server that is listening on the socket.

     void
     command_handler (int fd)
     {
       int i, rc;
       assuan_context_t ctx;

       if (fd == -1)
         {
           int filedes[2];

           filedes[0] = 0;
           filedes[1] = 1;
           rc = assuan_init_pipe_server (&ctx, filedes);
         }
       else
         rc = assuan_init_socket_server_ext (&ctx, fd, 2);
       if (rc)
         {
           fprintf (stderr, "server init failed: %s\n", gpg_strerror(rc));
           return;
         }

This is the first part of the command handler.  In case this is called as a pipe based server, FD will be based as fd and the code assumes that the server's stdin and stdout file handles are connected to a pipe.  The initialization is thus done using the function:

 -- Function: assuan_error_t assuan_init_pipe_server (assuan_context_t *R_CTX, int FILEDES[2])

     The function takes the two file descriptors from FILEDES and returns a new Assuan context at R_CTX.  As usual, a return value of 0 indicates success and a failure is indicated by a returning an error code.  In case of error, NULL will be stored at R_CTX.

     In case the server has been called using a bi-directional pipe (socketpair), FILEDES is ignored and the file descriptor is taken from the environment variable _assuan_connection_fd.  You won't need to know that because assuan_pipe_connect_ext, used by the client to connect to such a server, automagically sets this variable.

If a file descriptor has been passed, the assuan context gets initialized by the function:

 -- Function: assuan_error_t assuan_init_socket_server_ext (assuan_context_t *R_CTX, int FD, unsigned int FLAGS)

     The function takes the file descriptor FD which is expected to be associated with a socket and returns a new Assuan context at R_CTX. The following bits are currently defined for FLAGS:

     Bit 0
          If set, sendmsg and recvmesg are used for input and output and thus enabling the use of descriptor passing.

     Bit 1
          If set, FD refers to an already accepted socket.  That is, Libassuan won't call ACCEPT for it.  It is suggested to set this bit as it allows better control of the connection state.

     As usual, a return value of 0 indicates success and a failure is indicated by a returning an error code.  In case of error, NULL will be stored at R_CTX.

After error checking, the implemented assuan commands are registered with the server.

       for (i = 0; command_table[i].name; i++)
         {
           rc = assuan_register_command (ctx,
                                         command_table[i].name,
                                         command_table[i].handler);
           if (rc)
             {
               fprintf (stderr, "register failed: %s\n", gpg_strerror (rc));
               assuan_deinit_server (ctx);
               return;
             }
         }

 -- Function: assuan_error_t assuan_register_command (assuan_context_t CTX, const char *CMD_STRING, int (*HANDLER) (assuan_context_t, char *))

     This registers the command named CMD_STRING with the Assuan context CTX.  HANDLER is the function called by Libassuan if this command is received from the client.  NULL may be used for HANDLER to use a default handler (this only works with a few pre-defined commands).  Note that several default handlers have already been registered when the context has been created: ``NOP'', ``CANCEL'', ``OPTION'', ``BYE'', ``AUTH'', ``RESET'' and ``END''.  It is possible, but not recommended, to override these commands.

 -- Function: assuan_error_t assuan_register_post_cmd_notify (assuan_context_t CTX, void (*FNC)(assuan_context_t), int ERR)

     Register a function to be called right after a command has been processed.  ERR is the result code from the last internal assuan operation and not the one returned by the handler.  It may be used for command-related cleanup.

 -- Function: assuan_error_t assuan_register_bye_notify (assuan_context_t CTX, void (*FNC)(assuan_context_t))

     Register function FNC with context CTX to be called right before the standard handler for the ``BYE'' command is being called.

 -- Function: assuan_error_t assuan_register_reset_notify (assuan_context_t CTX, void (*FNC)(assuan_context_t))

     Register function FNC with context CTX to be called right before the standard handler for the ``RESET'' command is being called.

 -- Function: assuan_error_t assuan_register_cancel_notify (assuan_context_t CTX, void (*FNC)(assuan_context_t))

     Register function FNC with context CTX to be called right before the standard handler for the ``RESET'' command is being called.

 -- Function: assuan_error_t assuan_register_option_handler (assuan_context_t CTX, int (*FNC)(assuan_context_t, const char*, const char*))

     Register function FNC with context CTX for processing options.  That function is being called with the context, the name and the value of the option.  Leading and trailing spaces are removed from the name and the value.  The optional leading two dashes of the name are removed as well.  If no value has been given, an empty string is passed.  The function needs to return 0 on success or an error code.

 -- Function: assuan_error_t assuan_register_input_notify (assuan_context_t CTX, void (*FNC)(assuan_context_t, const char*))

     Although the input function may be overridden with a custom handler, it is often more convenient to use the default handler and to know whether an ``INPUT'' command has been seen and successfully parsed.  The second argument passed to that function is the entire line.  Because that line has already been parsed when the function gets called, a file descriptor set with the ``INPUT'' command may already be used.  That file descriptor is available by calling assuan_get_input_fd.

 -- Function: assuan_error_t assuan_register_output_notify (assuan_context_t CTX, void (*FNC)(assuan_context_t, const char*))

     Although the output function may be overridden with a custom handler, it is often more convenient to use the default handler and to know whether an ``OUTPUT'' command has been seen and successfully parsed.  The second argument passed to that function is the entire line.  Because that line has already been parsed when the function gets called, a file descriptor set with the ``OUTPUT'' command may already be used.  That file descriptor is available by calling assuan_get_output_fd.

 -- Function: assuan_error_t assuan_set_hello_line (assuan_context_t CTX, const char *LINE)

     This is not actually a register function but may be called also after registering commands. It changes the ``Hello'' line, sent by the server to the client as a first response, from a default string to the string LINE.  For logging purposes, it is often useful to use such a custom hello line which may tell version numbers and such. Linefeeds are allowed in this string, however, each line needs to be shorter than the Assuan line length limit.

As a last initialization step, debugging may be enabled for the current connection.  This is done using

 -- Function: void assuan_set_log_stream (assuan_context_t CTX, FILE *FP)

     Enable debugging for the context CTX and write all debugging output to the stdio stream FP.  If the default log stream (used for non-context specific events) has not yet been set, a call to this functions implicitly sets this stream also to FP.

Now that everything has been setup, we can start to process our clients requests.

       for (;;)
         {
           rc = assuan_accept (ctx);
           if (rc == -1)
             break;
           else if (rc)
             {
               fprintf (stderr, "accept problem: %s\n", gpg_strerror (rc));
               break;
             }

           rc = assuan_process (ctx);
           if (rc)
             {
               fprintf (stderr, "processing failed: %s\n", gpg_strerror (rc));
               continue;
             }
         }
       assuan_deinit_server (ctx);
     }

For future extensibility and to properly detect the end of the connection the core of the server should loop over the accept and process calls.

 -- Function: assuan_error_t assuan_accept (assuan_context_t CTX)

     A call to this function cancel any existing connection and waits for a connection from a client (that might be skipped, depending on the type of the server).  The initial handshake is performed which may include an initial authentication or encryption negotiation.  On success 0 is returned.  An error code will be returned if the connection could for some reason not be established.  An error code of -1 indicates the end of the connection.

 -- Function: assuan_error_t assuan_process (assuan_context_t CTX)

     This function is used to handle the Assuan protocol after a connection has been established using assuan_accept.  It is the main protocol handler responsible for reading the client commands and calling the appropriate handlers.  The function returns 0 on success or an error code if something went seriously wrong.  Error codes from the individual command handlers, i.e. operational error, are not seen here.

After the loop has terminated, the Assuan context needs to be released:

 -- Function: void assuan_deinit_server (assuan_context_t CTX)

     Releases the resources described by the Assuan context CTX It is explicitly allowed to pass NULL for CTX, in which case the function does nothing.

That is all needed for the server code.  You only need to come up with the code for the individual command handlers.  Take care that the line passed to the command handlers is allocated statically within the context and calls to Assuan functions may modify that line.  You are also allowed to modify that line which makes parsing much easier.

How to use external I/O event loops
***********************************

The above implementations of an Assuan client and server are synchronous, insofar the main routines block until a request or client connection is completely processed.  In some programs, for example GUI applications, this is undesirable.  Instead, Assuan operations should be non-blocking, and the caller should be able to poll all involved file descriptors to determine when the next Assuan function can be invoked without blocking.

To make this possible, client and server have to adhere to some rules:

  * Either partner should always write full lines.  If partial lines are written, the remainder of the line should b sent without delay.

  * Either partner should eagerly receive status messages.  While receiving and sending bulk data may be delayed, the status communication channel is different: Both partners may send status messages in blocking mode at any time the protocol allows them to send such status messages.  To ensure that these send operations do not actually block the sender, the recipient must be ready to receive without undue delay.

  * If descriptor passing is used over a socket, the descriptor must be sent after the corresponding command without undue delay.

Together, these restrictions allow to limit the need for asynchronous I/O operations to bulk data and the inbound status file descriptor.

In addition to the above rules, client and server should adhere to the following implementation guidelines.

External I/O event loops in the client.
=======================================

The reference implementation for using external I/O event loops in the client is the GPGME library, which exports its own external I/O event loop mechanism and utilizes the Assuan library transparently for the user.  The following steps document how GPGME achieves this.

 1. Before connecting, set up pipes for bulk data transfer (using the INPUT/OUTPUT commands, for example).  These are passed to the server either by inheritance (using a pipe server) or by FD passing (using a socket server).

 2. Then you need to connect to the server.  GPGME uses a pipe server, so it just spawns a server process, which is a non-blocking operation. FIXME: Currently, using a client with external event loop over a socket connection is not supported.  It is easy to support (we just need a variation of assuan_socket_connect which takes an already connected socket FD and turns it into an Assuan context), so if you need this let us know.

 3. After connecting, get the inbound status FD with assuan_get_active_fds (the first one returned is the status FD).  This FD can be duplicated if it is convenient (GPGME does this to be able to close this FD and associated callback handlers without disrupting Assuan's internals).

 4. Then register the Assuan inbound status FD and all bulk data FDs with the I/O event mechanism.  In general, this requires setting up callback handlers for these FDs and registering them with the main event loop.

 5. When bulk data FDs become ready, you can simply perform the corresponding read or write operations.  When the inbound status FD becomes ready, you can receive the next server line with assuan_read_line().

 6. You should close and unregister the bulk data FDs when you wrote all data (for outbound FDs) or receive an EOF (for inbound FDs).  When you receive an ERR from the server, or an OK for the final operation, you can unregister the inbound status FD and call assuan_disconnect to close it.

 7. As noted above, all send operations on the outbound status FD are done immediate with blocking.  In GPGME, this has never caused any problems.

 8. The INQUIRE function can be handled in two ways: If the requested data is immediately available, the client can just send the data blockingly.  If the requested data needs to be fetched from a blocking source, a callback handler can be registered for the FD with the main event loop.  GPGME does not support the INQUIRE function, so we do not have any practical experience with this.

Currently, the client can not cancel a pending operation gracefully. It can, however, disconnect from the server at any time.  It is the responsibility of the server to periodically send status messages to the client to probe if the connection remains alive.

External I/O event loops in the server.
=======================================

Currently, no Assuan server exists which uses external I/O event loops.  However, the following guidelines should lead to a usable implementation:

 1. For socket servers: You can not use assuan_accept, so you should just implement the bind/connect/listen/accept stage yourself. You can register the listen FD with your main event loop, accept the connection when it becomes ready, and finally call assuan_init_socket_server_ext with the final argument being 2 to create an Assuan context for this connection.  This way you can also handle multiple connections in parallel.  The reference implementation for this approach is DirMngr.

     For pipe servers: assuan_init_pipe_server creates an Assuan context valid for the pipe FDs.

 2. Once you have a context for a single connection, you can get the inbound status FD with assuan_get_active_fds (the first one returned is the status FD).  This FD can be duplicated if it is convenient.  Every time the inbound status FD is readable, you should invoke the function assuan_process_next (see below) to process the next incoming message.  assuan_process_next processes as many status lines as can be received by a single read operation.  When it returns, the inbound status FD may still be readable, but Assuan does not check this.

     The function assuan_process_next returns 0 if it can not make progress reliably, and it returns an end of file error code if the client closed the connection.  See below for more information on this function.

 3. The command will be dispatched by assuan_process_next just as with assuan_process, however, you will want to implement the command handlers in such a way that they do not block.  For example, the command handler may just register the bulk data FDs with the main event loop and return.

     When the command is finished, irregardless if this happens directly in the command handler or later, you must call assuan_process_done with an appropriate error code (or 0 for success) to return an appropriate status line to the client.  You can do this at the end of the command handler, for example by ending it with return assuan_process_done (error_code);.  Another possibility is to invoke assuan_process_done from the place in the code which closes the last active bulk FD registered with the main event loop for this operation.

It is not possible to use assuan_inquire in a command handler, as this function blocks on receiving the inquired data from the client.  Instead, the asynchronous version assuan_inquire_ext needs to be used (see below), which invokes a callback when the client provided the inquired data.  A typical usage would be for the command handler to register a continuation with assuan_inquire_ext and return 0.  Eventually, the continuation would be invoked by assuan_process_next when the client data arrived.  The continuation could complete the command and eventually call assuan_process_done.

Cancellation is supported by returning an appropriate error code to the client with assuan_process_done.  For long running operations, the server should send progress status messages to the client in regular intervals to notice when the client disconnects.

 -- Function: assuan_error_t assuan_process_next (assuan_context_t CTX)
     This is the same as assuan_process but the caller has to provide the outer loop.  He should loop as long as the return code is zero and stop otherwise; -1 or GPG_ERR_EOF indicate a regular end.

 -- Function: assuan_error_t assuan_inquire_ext (assuan_context_t CTX, const char *KEYWORD, unsigned char **R_BUFFER, size_t *R_LENGTH, size_t MAXLEN, int (*CB) (void *cb_data, int rc), void *CB_DATA)

     This is the same as assuan_inquire but the caller has to provide the outer loop (using assuan_process_next).  The caller should specify a continuation with CB, which receives CB_DATA as its first argument.

Utility functions
*****************

There are a lot of helper functions to make writing Assuan code easier. Some of these functions provide information not available with the general functions.

 -- Function: void assuan_set_pointer (assuan_context_t CTX, void *POINTER)

     Store the arbitrary pointer value POINTER into the context CTX.  This is useful to provide command handlers with additional application context.

 -- Function: void* assuan_get_pointer (assuan_context_t CTX)

     This returns the pointer for context CTX which has been set using the above function.  A common way to use it is by setting the pointer before starting the processing loop and to retrieve it right at the start of a command handler:

          static int
          cmd_foo (assuan_context_t ctx, char *line)
          {
            ctrl_t ctrl = assuan_get_pointer (ctx);
            ...
          }

 -- Function: assuan_error_t assuan_write_status (assuan_context_t CTX, const char *KEYWORD, const char *TEXT)

     This is a convenience function for a server to send a status line.  You need to pass it the KEYWORD and the content of the status line in TEXT.

 -- Function: assuan_error_t assuan_inquire (assuan_context_t CTX, const char *KEYWORD, unsigned char **R_BUFFER, size_t *R_LENGTH, size_t MAXLEN)

     A server may use this function to inquire data from a client.  It sends an ``INQUIRE'' command back to the server and returns the response conveniently in a newly allocated buffer.  You need to pass at least the server's context CTX and the KEYWORD describing the requested data.  All other parameters may be NULL or 0, although this is rarely useful.

     On success the result is stored in a newly allocated buffer stored at R_BUFFER. The length of the data is stored at R_LENGTH.  If MAXLEN has not been given as 0, it describes an upper size limited of the expected data.  If the client returns too much data the function fails and the error code GPG_ERR_ASS_TOO_MUCH_DATA will be returned.

 -- Function: FILE* assuan_get_data_fp (assuan_context_t CTX)

     Return a stdio stream for the Assuan context CTX.  This stream may then be used for data output (assuan_write_data).  The stream is valid until the end of the current handler.  Calling fclose for that stream is not required.  Assuan does all the buffering needed to insert the status line as well as the required line wrapping and quoting for data lines.

     This function is only available on systems supporting either funopen or fopencookie. If it is not supported NULL is returned and errno is set to ENOSYS.

 -- Function: assuan_error_t assuan_set_okay_line (assuan_context_t CTX, const char *LINE)

     Set the text used for the next ``OK'' response to LINE.  This is sometimes useful to send additional human readable information along with the OK line.  The string is automatically reset at the end of the current handler.

 -- Function: assuan_error_t assuan_command_parse_fd (assuan_context_t CTX, char *LINE, int *RFD)

     This is the core of the default ``INPUT'' and ``OUTPUT'' handler.  It may be used in custom commands as well to negotiate a file descriptor. If LINE contains FD=N, it returns N in RFD assuming a local file descriptor.  If LINE contains just FD it returns a file descriptor at RFD; this file descriptor needs to have been sent by the client right before using assuan_sendfd.

     On W32 systems the returned file descriptor is a system handle and not a libc low level I/O file descriptor.  Thus applications need to use _open_osfhandle before they can pass this descriptor to standard functions like fdopen or dup.

 -- Function: int assuan_get_input_fd (assuan_context_t CTX)

     Return the file descriptor sent by the client using the last ``INPUT'' command.  Returns -1 if no file descriptor is available.

 -- Function: int assuan_get_output_fd (assuan_context_t CTX)

     Return the file descriptor sent by the client using the last ``OUTPUT'' command.  Returns -1 if no file descriptor is available.

 -- Function: assuan_error_t assuan_close_input_fd (assuan_context_t CTX)

     Close the file descriptor set by the last ``INPUT'' command.  This function has the advantage over a simple close that it can do some sanity checks and make sure that a following assuan_get_input_fd won't return an already closed descriptor.

 -- Function: assuan_error_t assuan_close_output_fd (assuan_context_t CTX)

     Close the file descriptor set by the last ``OUTPUT'' command.  This function has the advantage over a simple close that it can do some sanity checks and make sure that a following assuan_get_input_fd won't return an already closed descriptor.

 -- Function: int assuan_set_error (assuan_context_t CTX, int ERR, const char *TEXT)

     This is a helper to provide a more descriptive error text with ``ERR'' lines.  For this to work, the text needs to be stored in the context CTX while still being in the command handler.  This function is commonly called this way

            return assuan_set_error (ctx, err, "commands needs 5 arguments");

     The value ERR is passed through and thus the return value of the command handler in the example.  The provided text further explains that error code to humans.

 -- Function: void assuan_set_flag (assuan_context_t CTX, assuan_flag_t FLAG, int VALUE)

     Set the the FLAG for context CTX to VALUE.  Values for flags are usually 1 or 0 but certain flags might need other values.

      -- Data type: assuan_flag_t
          The flags are all named and collected in an enum for better readability. Currently only one flag is defined:

          ASSUAN_NO_WAITPID
               When using a pipe server, by default Libassuan will wait for the forked process to die in assuan_disconnect.  In certain cases this is not desirable.  By setting this flag, a call to waitpid will be suppressed and the caller is responsible to cleanup the child process.

          ASSUAN_CONFIDENTIAL
               Uses to return the state of the confidential logging mode.  For changing this mode the functions assuan_begin_confidential and assuan_end_confidential should be used.

 -- Function: int assuan_get_flag (assuan_context_t CTX, assuan_flag_t FLAG)
     Return the value of FLAG in context CTX.

 -- Function: const char* assuan_strerror (assuan_error_t ERR)

     This function returns a textual representation of the given error code ERR. If this is an unknown value, a string with the value is returned. (Beware: it is hold in a static buffer).  It is suggested that gpg-error style error numbers should be used and thus gpg_strerror be called. See function assuan_set_assuan_err_source, on how to enable these error codes.

 -- Function: pid_t assuan_get_pid (assuan_context_t CTX)

     This function returns the pid of the connected connected peer.  If that pid is not known -1 is returned.  Note that it is not always possible to learn the pid of the other process. For a pipe based server the client knows it instantly and a mechanism is in place to let the server learn it.  For socket based servers the pid is only available on systems providing the ``SO_PEERCRED'' socket option  (to our knowledge only the Linux kernel has this feature).

 -- Function: assuan_error_t assuan_get_peercred (assuan_context_t CTX, pid_t *PID, uid_t *UID, gid_t *PID)

     Return user credentials of the peer. This will work only on certain systems and only when connected over a socket.  If you are not interested in some of the values, pass NULL instead of the address of an appropriate variable.  PID, UID and GID are only set if the function succeeds and returns with 0.

     As of now only the server is able to retrieve this information.  Note, that for getting the pid of the peer assuan_get_pid is usually better suited.

 -- Function: int assuan_get_active_fds (assuan_context_t CTX, int WHAT, int *FDARRAY, int FDARRAYSIZE)

     Return all active file descriptors for the context CTX.  This function can be used to select on the file descriptors and to call assuan_process_next if there is an active one.  The first descriptor in the array is the one used for the command connection. Currently WHAT needs to be 0 to return descriptors used for reading, 1 will eventually be used to return descriptors used for writing.  FDARRAY is an array of integers provided by the caller; FDARRAYSIZE gives the size of that array.

     On success the number of active descriptors are returned.  These active descriptors are then stored in FDARRAY.  On error -1 is returned; the most likely reason for this is a too small FDARRAY.

     Note that on W32 systems the returned file descriptor is a system handle and not a libc low level I/O file descriptor.

 -- Function: int assuan_pending_line (assuan_context_t CTX)
     A call to this function return true if a full line has been buffered and thus an entire assuan line may be read without triggering any actual I/O.

 -- Function: void assuan_set_io_monitor (assuan_context_t CTX, unsigned int (*MONITOR)(assuan_context_t CTX, int DIRECTION, const char *LINE, size_t LINELEN))

     This function registers an I/O monitor for the context CTX.  Such a monitor function is called right after a line has been received or just before it is send.  With DIRECTION set to 1 the monitor has been called for an output operation; 0 obviosuly means it has been called for an input operation.  If the monitor sets bit 0 in the return value, any active logging of the line will be suppressed.  With bit 1 set, the entire line will be ignored.

 -- Function: void assuan_begin_confidential (assuan_context_t CTX)

     Put the logging feature into confidential mode.  This is to avoid logging of sensitive data.

 -- Function: void assuan_end_confidential (assuan_context_t CTX)

     Get the logging feature out of confidential mode.  All data will be logged again (if logging is enabled).

 -- Function: FILE* assuan_get_assuan_log_stream (void)

     Return the stream which is currently being using for global logging.

 -- Function: const char* assuan_get_assuan_log_prefix (void)

     Return the prefix to be used at the start of a line emitted by assuan on the log stream.  The default implementation returns the empty string.

     [file lgpl.texi not included]
     [file gpl.texi not included]