Warning

This is a design page. It was used to design and discuss the initial implementation of the change. However, the state of this document does not necessarily correspond to the current state of the implementation since we do not keep this document up to date with further changes and bug fixes.

Simple D-Bus API wrapper library

Related ticket(s):

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.

  • 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)

/**
 * @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);

/**
 * @}
 */