Simple D-Bus API wrapper library

Related ticket(s):

Problem Statement

Using D-Bus requires a significant amount of knowledge of D-Bus and its underlying library API. Libraries like libdbus or libdbus_glib are quite complex and requires a lot of code to do even the simplest things. The purpose of this document is to describe a new public API to access most fundamental parts of SSSD’s D-Bus responder in a simple way so that a user doesn’t have to deal with D-Bus at all.

Prerequisites

  • Each attribute of every D-Bus object accessible via this API is represented as string.
  • Naming convention of D-Bus methods:
    • List<class><condition>(arg1, …) returning array of object paths
      • ListUsers()
      • ListDomains()
      • ListUsersByName(filter)
      • ListGroupsByName(filter)
    • Find<class><condition>(arg1, …) returning single object path
      • FindUserById(id)
      • FindDomainByName(name)

The API

/**
 * @defgroup sss_dbus Simple interface to SSSD InfoPipe responder.
 * Libsss_dbus provides a synchronous interface to simplify basic communication
 * with SSSD InfoPipe responder.
 * @{
 */

/** SSSD InfoPipe bus address */
#define SSS_DBUS_IFP "org.freedesktop.sssd.infopipe"

/** SSSD InfoPipe interface */
#define SSS_DBUS_IFACE_IFP SSS_DBUS_IFP
#define SSS_DBUS_IFACE_COMPONENTS "org.freedesktop.sssd.infopipe.Components"
#define SSS_DBUS_IFACE_SERVICES "org.freedesktop.sssd.infopipe.Services"
#define SSS_DBUS_IFACE_DOMAINS "org.freedesktop.sssd.infopipe.Domains"
#define SSS_DBUS_IFACE_USERS "org.freedesktop.sssd.infopipe.Users"
#define SSS_DBUS_IFACE_GROUPS "org.freedesktop.sssd.infopipe.Groups"

/**
 * Opaque libsss_dbus context. One context shall not be used by multiple
 * threads. Each thread needs to create and use its own context.
 *
 * @see sss_dbus_init
 * @see sss_dbus_init_ex
 */
typedef struct sss_dbus_ctx sss_dbus_ctx;

/**
 * Typedef for memory allocation functions
 */
typedef void (sss_dbus_free_func)(void *ptr, void *pvt);
typedef void *(sss_dbus_alloc_func)(size_t size, void *pvt);

/**
 * Error codes used by libsss_dbus
 */
typedef enum sss_dbus_error {
    /** Success */
    SSS_DBUS_OK = 0,

    /** Ran out of memory during processing */
    SSS_DBUS_OUT_OF_MEMORY,

    /** Invalid argument */
    SSS_DBUS_INVALID_ARGUMENT,

    /**
     * Input/output error
     *
     * @see sss_dbus_get_last_io_error() to get more information
     */
    SSS_DBUS_IO_ERROR,

    /** Internal error */
    SSS_DBUS_INTERNAL_ERROR,

    /** Operation not supported */
    SSS_DBUS_NOT_SUPPORTED,

    /** Attribute does not exist */
    SSS_DBUS_ATTR_MISSING,

    /** Attribute does not have any value set */
    SSS_DBUS_ATTR_NULL,

    /** Incorrect attribute type */
    SSS_DBUS_INCORRECT_TYPE,

    /** Always last */
    SSS_DBUS_ERROR_SENTINEL
} sss_dbus_error;

/**
 * Boolean type
 */
typedef uint32_t sss_dbus_bool;

/**
 * D-Bus object attribute
 */
typedef struct sss_dbus_attr sss_dbus_attr;

/**
 * String dictionary
 */
typedef struct {
    char *key;
    char **values;
    unsigned int num_values;
} sss_dbus_str_dict;

/**
 * D-Bus object
 */
typedef struct sss_dbus_object {
    char *name;
    char *object_path;
    char *interface;
    sss_dbus_attr **attrs;
} sss_dbus_object;

/**
 * @brief Initialize sss_dbus context using default allocator (malloc)
 *
 * @param[out] _ctx sss_dbus context
 */
sss_dbus_error
sss_dbus_init(sss_dbus_ctx **_ctx);

/**
 * @brief Initialize sss_dbus context
 *
 * @param[in] alloc_pvt  Private data for allocation routine
 * @param[in] alloc_func Function to allocate memory for the context, if
 *                       NULL malloc() is used
 * @param[in] free_func  Function to free the memory of the context, if
 *                       NULL free() is used
 * @param[out] _ctx      sss_dbus context
 */
sss_dbus_error
sss_dbus_init_ex(void *alloc_pvt,
                 sss_dbus_alloc_func *alloc_func,
                 sss_dbus_free_func *free_func,
                 sss_dbus_ctx **_ctx);

/**
 * @brief Return last error message from underlying D-Bus communication
 *
 * @param[in] ctx sss_dbus context
 * @return Error message or NULL if no error occurred during last D-Bus call.
 */
const char *
sss_dbus_get_last_io_error(sss_dbus_ctx *ctx);

/**
 * @brief Return default interface for object with path @object_path.
 *
 * @param[in] ctx object_path D-Bus object path
 * @return Interface name or NULL if the object path is unknown.
 */
const char *
sss_dbus_get_iface_for_object(const char *object_path);

/**
 * @brief Create message for SSSD InfoPipe bus.
 *
 * @param[in] object_path D-Bus object path
 * @param[in] interface   D-Bus interface
 * @param[in] method      D-Bus method
 *
 * @return D-Bus message.
 */
DBusMessage *
sss_dbus_create_message(const char *object_path,
                        const char *interface,
                        const char *method);

/**
 * @brief Send D-Bus message to SSSD InfoPipe bus.
 *
 * @param[in] ctx         sss_dbus context
 * @param[in] interface   D-Bus interface
 * @param[in] object_path D-Bus object path
 * @param[in] method      D-Bus method
 *
 * @return D-Bus message.
 */
sss_dbus_error
sss_dbus_send_message(sss_dbus_ctx *ctx,
                      DBusMessage *msg,
                      DBusMessage **_reply);

/**
 * @brief Fetch selected attributes of given object.
 *
 * @param[in] ctx         sss_dbus context
 * @param[in] object_path D-Bus object path
 * @param[in] interface   D-Bus interface
 * @param[in] name        Name of desired attribute
 * @param[out] _attrs     List of acquired attributes
 */
sss_dbus_error
sss_dbus_fetch_attr(sss_dbus_ctx *ctx,
                    const char *object_path,
                    const char *name,
                    const char *interface,
                    sss_dbus_attr ***_attrs);

/**
 * @brief Fetch all attributes of given object.
 *
 * @param[in] ctx         sss_dbus context
 * @param[in] object_path D-Bus object path
 * @param[in] interface   D-Bus interface
 * @param[out] _attrs     Acquired attributes
 */
sss_dbus_error
sss_dbus_fetch_all_attrs(sss_dbus_ctx *ctx,
                         const char *object_path,
                         const char *interface,
                         sss_dbus_attr ***_attrs);

/**
 * @brief Fetch D-Bus object.
 *
 * @param[in] ctx         sss_dbus context
 * @param[in] object_path D-Bus object path
 * @param[in] interface   D-Bus interface
 * @param[out] _object    Object and its attributes
 */
sss_dbus_error
sss_dbus_fetch_object(sss_dbus_ctx *ctx,
                      const char *object_path,
                      const char *interface,
                      sss_dbus_object **_object);

/**
 * @brief List objects that satisfies given conditions. This routine will
 * invoke List<method> D-Bus method on SSSD InfoPipe interface. Arguments
 * to this method are given as standard variadic D-Bus arguments.
 *
 * @param[in] ctx            sss_dbus context
 * @param[in] method         D-Bus method to call without the 'List' prefix
 * @param[out] _object_paths List of object paths
 * @param[in] first_arg_type Type of the first D-Bus argument
 * @param[in] ...            D-Bus arguments
 */
sss_dbus_error
sss_dbus_invoke_list(sss_dbus_ctx *ctx,
                     const char *method,
                     char ***_object_paths,
                     int first_arg_type,
                     ...);

/**
 * @brief Find single object that satisfies given conditions. This routine will
 * invoke Find<method> D-Bus method on SSSD InfoPipe interface. Arguments
 * to this method are given as standard variadic D-Bus arguments.
 *
 * @param[in] ctx            sss_dbus context
 * @param[in] method         D-Bus method to call without the 'Find' prefix
 * @param[out] _object_path Object path
 * @param[in] first_arg_type Type of the first D-Bus argument
 * @param[in] ...            D-Bus arguments
 */
sss_dbus_error
sss_dbus_invoke_find(sss_dbus_ctx *ctx,
                     const char *method,
                     char **_object_path,
                     int first_arg_type,
                     ...);

/**
 * @brief Find attribute in list and return its value.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _value Output value
 */
sss_dbus_error
sss_dbus_find_attr_as_bool(sss_dbus_attr **attrs,
                           const char *name,
                           sss_dbus_bool *_value);

/**
 * @brief Find attribute in list and return its value.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _value Output value
 */
sss_dbus_error
sss_dbus_find_attr_as_int16(sss_dbus_attr **attrs,
                            const char *name,
                            int16_t *_value);

/**
 * @brief Find attribute in list and return its value.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _value Output value
 */
sss_dbus_error
sss_dbus_find_attr_as_uint16(sss_dbus_attr **attrs,
                             const char *name,
                             uint16_t *_value);

/**
 * @brief Find attribute in list and return its value.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _value Output value
 */
sss_dbus_error
sss_dbus_find_attr_as_int32(sss_dbus_attr **attrs,
                            const char *name,
                            int32_t *_value);

/**
 * @brief Find attribute in list and return its value.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _value Output value
 */
sss_dbus_error
sss_dbus_find_attr_as_uint32(sss_dbus_attr **attrs,
                             const char *name,
                             uint32_t *_value);

/**
 * @brief Find attribute in list and return its value.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _value Output value
 */
sss_dbus_error
sss_dbus_find_attr_as_int64(sss_dbus_attr **attrs,
                            const char *name,
                            int64_t *_value);

/**
 * @brief Find attribute in list and return its value.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _value Output value
 */
sss_dbus_error
sss_dbus_find_attr_as_uint64(sss_dbus_attr **attrs,
                             const char *name,
                             uint64_t *_value);

/**
 * @brief Find attribute in list and return its value.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _value Output value
 */
sss_dbus_error
sss_dbus_find_attr_as_string(sss_dbus_attr **attrs,
                             const char *name,
                             const char **_value);

/**
 * @brief Find attribute in list and return its value.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _value Output value
 */
sss_dbus_error
sss_dbus_find_attr_as_string_dict(sss_dbus_attr **attrs,
                                  const char *name,
                                  sss_dbus_str_dict *_value);

/**
 * @brief Find attribute in list and return its values.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _num_values Number of values in the array
 * @param[out] _values Output array
 */
sss_dbus_error
sss_dbus_find_attr_as_bool_array(sss_dbus_attr **attrs,
                                 const char *name,
                                 unsigned int *_num_values,
                                 sss_dbus_bool **_value);

/**
 * @brief Find attribute in list and return its values.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _num_values Number of values in the array
 * @param[out] _values Output array
 */
sss_dbus_error
sss_dbus_find_attr_as_int16_array(sss_dbus_attr **attrs,
                                  const char *name,
                                  unsigned int *_num_values,
                                  int16_t **_value);

/**
 * @brief Find attribute in list and return its values.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _num_values Number of values in the array
 * @param[out] _values Output array
 */
sss_dbus_error
sss_dbus_find_attr_as_uint16_array(sss_dbus_attr **attrs,
                                   const char *name,
                                   unsigned int *_num_values,
                                   uint16_t **_value);

/**
 * @brief Find attribute in list and return its values.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _num_values Number of values in the array
 * @param[out] _values Output array
 */
sss_dbus_error
sss_dbus_find_attr_as_int32_array(sss_dbus_attr **attrs,
                                  const char *name,
                                  unsigned int *_num_values,
                                  int32_t **_value);

/**
 * @brief Find attribute in list and return its values.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _num_values Number of values in the array
 * @param[out] _values Output array
 */
sss_dbus_error
sss_dbus_find_attr_as_uint32_array(sss_dbus_attr **attrs,
                                   const char *name,
                                   unsigned int *_num_values,
                                   uint32_t **_value);

/**
 * @brief Find attribute in list and return its values.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _num_values Number of values in the array
 * @param[out] _values Output array
 */
sss_dbus_error
sss_dbus_find_attr_as_int64_array(sss_dbus_attr **attrs,
                                  const char *name,
                                  unsigned int *_num_values,
                                  int64_t **_value);

/**
 * @brief Find attribute in list and return its values.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _num_values Number of values in the array
 * @param[out] _values Output array
 */
sss_dbus_error
sss_dbus_find_attr_as_uint64_array(sss_dbus_attr **attrs,
                                   const char *name,
                                   unsigned int *_num_values,
                                   uint64_t **_value);

/**
 * @brief Find attribute in list and return its values.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _num_values Number of values in the array
 * @param[out] _values Output array
 */
sss_dbus_error
sss_dbus_find_attr_as_string_array(sss_dbus_attr **attrs,
                                   const char *name,
                                   unsigned int *_num_values,
                                   const char * const **_value);

/**
 * @brief Find attribute in list and return its values.
 *
 * @param[in] attrs Attributes
 * @param[in] name Name of the attribute to find
 * @param[out] _num_values Number of values in the array
 * @param[out] _values Output array
 */
sss_dbus_error
sss_dbus_find_attr_as_string_dict_array(sss_dbus_attr **attrs,
                                        const char *name,
                                        unsigned int *_num_values,
                                        sss_dbus_str_dict **_value);

/**
 * @brief Free sss_dbus context and set it to NULL.
 *
 * @param[in,out] _ctx sss_dbus context
 */
void
sss_dbus_free(sss_dbus_ctx **_ctx);

/**
 * @brief Free attribute list and set it to NULL.
 *
 * @param[in,out] _attrs Attributes
 */
void
sss_dbus_free_attrs(sss_dbus_ctx *ctx,
                    sss_dbus_attr ***_attrs);

/**
 * @brief Free sss_dbus object and set it to NULL.
 *
 * @param[in,out] _object Object
 */
void
sss_dbus_free_object(sss_dbus_ctx *ctx,
                     sss_dbus_object **_object);

/**
 * @brief Free string and set it to NULL.
 *
 * @param[in,out] _str String
 */
void
sss_dbus_free_string(sss_dbus_ctx *ctx,
                     char **_str);

/**
 * @brief Free array of strings and set it to NULL.
 *
 * @param[in,out] _str_array Array of strings
 */
void
sss_dbus_free_string_array(sss_dbus_ctx *ctx,
                           char ***_str_array);

/**
 * @}
 */

/**
 * @defgroup common Most common use cases of SSSD InfoPipe responder.
 * @{
 */

/**
 * @brief List names of available domains.
 *
 * @param[in] ctx       sss_dbus context
 * @param[out] _domains List of domain names
 */
sss_dbus_error
sss_dbus_list_domains(sss_dbus_ctx *ctx,
                      char ***_domains);

/**
 * @brief Fetch all information about domain by name.
 *
 * @param[in] ctx      sss_dbus context
 * @param[in] name     Domain name
 * @param[out] _domain Domain object
 */
sss_dbus_error
sss_dbus_fetch_domain_by_name(sss_dbus_ctx *ctx,
                              const char *name,
                              sss_dbus_object **_domain);

/**
 * @brief Fetch all information about user by uid.
 *
 * @param[in] ctx    sss_dbus context
 * @param[in] uid    User ID
 * @param[out] _user User object
 */
sss_dbus_error
sss_dbus_fetch_user_by_uid(sss_dbus_ctx *ctx,
                           uid_t uid,
                           sss_dbus_object **_user);

/**
 * @brief Fetch all information about user by name.
 *
 * @param[in] ctx    sss_dbus context
 * @param[in] name   User name
 * @param[out] _user User object
 */
sss_dbus_error
sss_dbus_fetch_user_by_name(sss_dbus_ctx *ctx,
                            const char *name,
                            sss_dbus_object **_user);

/**
 * @}
 */

Authors