## InfSaslContext InfSaslContext — Asynchronous SASL processing |

## Stability Level

Unstable, unless otherwise indicated

## Functions

void | (*InfSaslContextCallbackFunc) ()
void | (*InfSaslContextSessionFeedFunc) ()
InfSaslContext * | inf_sasl_context_new ()
InfSaslContext * | inf_sasl_context_ref ()
void | inf_sasl_context_unref ()
void | inf_sasl_context_set_callback ()
InfSaslContextSession * | inf_sasl_context_client_start_session ()
char * | inf_sasl_context_client_list_mechanisms ()
gboolean | inf_sasl_context_client_supports_mechanism ()
const char * | inf_sasl_context_client_suggest_mechanism ()
InfSaslContextSession * | inf_sasl_context_server_start_session ()
char * | inf_sasl_context_server_list_mechanisms ()
gboolean | inf_sasl_context_server_supports_mechanism ()
void | inf_sasl_context_stop_session ()
const char * | inf_sasl_context_session_get_property ()
void | inf_sasl_context_session_set_property ()
void | inf_sasl_context_session_continue ()
void | inf_sasl_context_session_feed ()
gboolean | inf_sasl_context_session_is_processing ()

## Types and Values

| InfSaslContext
| InfSaslContextSession

## Object Hierarchy

        GBoxed
        ╰── InfSaslContext

## Includes

    #include <libinfinity/common/inf-sasl-context.h>

## Description

InfSaslContext is a wrapper for the Gsasl library. It basically adds functionality to provide properties asynchronously to Gsasl, so that for example a dialog can be shown to the user before continuing with the authentication process. With Gsasl, it is expected that the callback function sets the requested property before returning, which makes it hard to give control back to a main loop while waiting for user input.

This wrapper makes sure the callback is called in another thread so that it can block without affecting the rest of the program. Use `inf_sasl_context_session_feed()` as a replacement for `gsasl_step64()`. Instead of returning the result data directly, the function calls a callback once all properties requested have been provided.

All threading internals are hidden by the wrapper, so all callbacks are issued in the user thread. However, it requires an InfIo object to dispatch messages to it. Also, all InfSaslContext functions are fully thread-safe.

## Functions

### InfSaslContextCallbackFunc ()

    void
    (*InfSaslContextCallbackFunc) (InfSaslContextSession *session,
                                   Gsasl_property property,
                                   gpointer session_data,
                                   gpointer user_data);

This callback is called whenever a property is required to proceed with authentication. For example, when a password is required, the callback is called with `property` set to `GSASL_PASSCODE`.

The function is then expected to set that property using `inf_sasl_context_session_set_property()` and, once it is done, call `inf_sasl_context_session_continue()`. This can happen fully asynchronously, that is it does not need to take place directly within the callback but the callback can, for example, open a dialog for the user to enter a password and then once the user closes the dialog call the two functions mentioned above.

#### Parameters

session | A InfSaslContextSession. |
property | The property requested. |
session_data | The session data for session specified in `inf_sasl_context_server_start_session()` or `inf_sasl_context_client_start_session()`. |
user_data | The user data specified in `inf_sasl_context_set_callback()`. |

### InfSaslContextSessionFeedFunc ()

    void
    (*InfSaslContextSessionFeedFunc) (InfSaslContextSession *session,
                                      const char *data,
                                      gboolean needs_more,
                                      const GError *error,
                                      gpointer user_data);

This function is called in response to `inf_sasl_context_session_feed()`. When all required properties (if any) have been provided by the callback function then this function is called with the response to send to the remote site.

If an error occurred then `error` will be set and `data` will be `NULL`.

#### Parameters

session | A InfSaslContextSession. |
data | The response to the fed data, base64 encoded and null-terminated. |
needs_more | If `TRUE` then `inf_sasl_context_session_feed()` needs to be called again with more data, otherwise the authentication has finished. |
error | This is nonzero if an error occurred while processing the input data. |
user_data | The user data specified in `inf_sasl_context_session_feed()`. |

### inf_sasl_context_new ()

    InfSaslContext *
    inf_sasl_context_new (GError **error);

Creates a new InfSaslContext with a reference count of 1. If the function fails it returns `NULL` and `error` is set.

[constructor]

#### Parameters

error | Location to store error information, if any. |

#### Returns

A new InfSaslContext, or `NULL` on error. Free with `inf_sasl_context_unref()` when no longer needed.

[transfer full]

### inf_sasl_context_ref ()

    InfSaslContext *
    inf_sasl_context_ref (InfSaslContext *context);

Increases the reference count of `context` by one.

#### Parameters

context | A InfSaslContext. |

#### Returns

The passed in pointer, `context` .

### inf_sasl_context_unref ()

    void
    inf_sasl_context_unref (InfSaslContext *context);

Decreases the reference count of `sasl` by one. When the reference count reaches zero then the object is freed and may no longer be used. If that happens then also all sessions created with `inf_sasl_context_client_start_session()` or `inf_sasl_context_server_start_session()` are stopped automatically.

#### Parameters

context | A InfSaslContext. |

### inf_sasl_context_set_callback ()

    void
    inf_sasl_context_set_callback (InfSaslContext *context,
                                   InfSaslContextCallbackFunc callback,
                                   gpointer user_data,
                                   GDestroyNotify notify);

Sets the callback to call when, during authentication, a certain properties needs to be provided, such as a username or a password. The callback function is expected to set the requested property using `inf_sasl_context_session_set_property()` and then call `inf_sasl_context_session_continue()` with retval being GSASL_OK. If it cannot provide the property then it should only call `inf_sasl_context_session_continue()` with retval indicating the problem.

The callback function does not need to provide the property immediately. It is also allowed return and call `inf_sasl_context_session_continue()` later.

#### Parameters

context | A InfSaslContext. |
callback | A function to call to query properties for authentication. |
user_data | Additional context to pass to `callback` . |
notify | Function called to destroy `user_data` once it is no longer needed, or `NULL`. |

### inf_sasl_context_client_start_session ()

    InfSaslContextSession *
    inf_sasl_context_client_start_session (InfSaslContext *context,
                                           InfIo *io,
                                           const char *mech,
                                           gpointer session_data,
                                           GError **error);

Starts a new client-side SASL session using `mech` for authentication. When the session finished, that is either when an error occurred or the authentication finished successfully, use `inf_sasl_context_stop_session()`.

The callback function will be called in the thread that `io` runs in.

#### Parameters

context | A InfSaslContext. |
io | The InfIo main loop to which to dispatch callbacks. |
mech | The mechanism to use for the session. |
session_data | Session-specific data to provide to the InfSaslContextCallbackFunc. |
error | Location to store error information, if any. |

#### Returns

A InfSaslContextSession.

[transfer none]

### inf_sasl_context_client_list_mechanisms ()

    char *
    inf_sasl_context_client_list_mechanisms
                                   (InfSaslContext *context,
                                    GError **error);

Returns a newly allocated space-separated string containing SASL mechanisms that `context` supports for client sessions.

#### Parameters

context | A InfSaslContext. |
error | Location to store error information, if any. |

#### Returns

A newly allocated string. Free with `g_free()` when no longer in use.

[transfer full]

### inf_sasl_context_client_supports_mechanism ()

    gboolean
    inf_sasl_context_client_supports_mechanism
                                   (InfSaslContext *context,
                                    const char *mech);

Checks whether `context` supports the mechanism with name `mech` for client sessions.

#### Parameters

context | A InfSaslContext. |
mech | The name of the mechanism to be tested. |

#### Returns

`TRUE` if `mech` is supported or `FALSE` otherwise.

### inf_sasl_context_client_suggest_mechanism ()

    const char *
    inf_sasl_context_client_suggest_mechanism
                                   (InfSaslContext *context,
                                    const char *mechanisms);

Given a list of SASL mechanisms this function suggests the which is the "best" one to be used.

#### Parameters

context | A InfSaslContext. |
mechanisms | Space-separated list of SASL mechanism names. |

#### Returns

The name of the suggested mechanism.

[transfer none]

### inf_sasl_context_server_start_session ()

    InfSaslContextSession *
    inf_sasl_context_server_start_session (InfSaslContext *context,
                                           InfIo *io,
                                           const char *mech,
                                           gpointer session_data,
                                           GError **error);

Starts a new server-side SASL session using `mech` for authentication. When the session finished, that is either when an error occurred or the authentication finished successfully, use `inf_sasl_context_stop_session()`.

The callback function will be called in the thread that `io` runs in.

#### Parameters

context | A InfSaslContext. |
io | The InfIo main loop to which to dispatch callbacks. |
mech | The mechanism to use for the session. |
session_data | Session-specific data to provide to the InfSaslContextCallbackFunc. |
error | Location to store error information, if any. |

#### Returns

A InfSaslContextSession.

[transfer none]

### inf_sasl_context_server_list_mechanisms ()

    char *
    inf_sasl_context_server_list_mechanisms
                                   (InfSaslContext *context,
                                    GError **error);

Returns a newly allocated space-separated string containing SASL mechanisms that `context` supports for server sessions.

#### Parameters

context | A InfSaslContext. |
error | Location to store error information, if any. |

#### Returns

A newly allocated string. Free with `g_free()` when no longer in use.

[transfer full]

### inf_sasl_context_server_supports_mechanism ()

    gboolean
    inf_sasl_context_server_supports_mechanism
                                   (InfSaslContext *context,
                                    const char *mech);

Checks whether `context` supports the mechanism with name `mech` for server sessions.

#### Parameters

context | A InfSaslContext. |
mech | The name of the mechanism to be tested. |

#### Returns

`TRUE` if `mech` is supported or `FALSE` otherwise.

### inf_sasl_context_stop_session ()

    void
    inf_sasl_context_stop_session (InfSaslContext *context,
                                   InfSaslContextSession *session);

Finishes `session` and frees all resources allocated to it. This can be used to cancel an authentication session, or to free it after it finished (either successfully or not).

`session` should no longer be used after this function was called.

#### Parameters

context | A InfSaslContext. |
session | A InfSaslContextSession created with `context` . |

### inf_sasl_context_session_get_property ()

    const char *
    inf_sasl_context_session_get_property (InfSaslContextSession *session,
                                           Gsasl_property prop);

Returns the value of the property `prop` in `session` . If the value does not yet exist then this function returns `NULL`. It does not invoke the InfSaslContextCallbackFunc to query it.

#### Parameters

session | A InfSaslContextSession. |
prop | A SASL property. |

#### Returns

The value of the property, or `NULL`. The value is owned by the session and must not be freed.

[allow-none]

### inf_sasl_context_session_set_property ()

    void
    inf_sasl_context_session_set_property (InfSaslContextSession *session,
                                           Gsasl_property prop,
                                           const char *value);

Sets the property `prop` in `session` to `value` .

#### Parameters

session | A InfSaslContextSession. |
prop | A SASL property. |
value | The value to set the property to. | [allow-none]

### inf_sasl_context_session_continue ()

    void
    inf_sasl_context_session_continue (InfSaslContextSession *session,
                                       int retval);

When the callback function specified in `inf_sasl_context_set_callback()` is called then `session` waits for the user to call `inf_sasl_context_session_continue()`. It should do so once it provided the requested property using `inf_sasl_context_session_set_property()` with `retval` being `GSASL_OK`. If it decides that the property cannot be provided then it should still call this function with `retval` being a SASL error code specifying the problem.

#### Parameters

session | A InfSaslContextSession. |
retval | Error code of the operation requested. |

### inf_sasl_context_session_feed ()

    void
    inf_sasl_context_session_feed (InfSaslContextSession *session,
                                   const char *data,
                                   InfSaslContextSessionFeedFunc func,
                                   gpointer user_data);

This function feeds data from the session's remote counterpart to `session` . It should be base64 encoded. This function will, asynchronously, process the data and query for properties it requires to do so. Once it has finished, `func` is called with output data to send to the remote side to be fed to its session counterpart.

This function must not be called again before `func` was called.

#### Parameters

session | A InfSaslContextSession. |
data | The data to feed to the SASL session. |
func | The function to call when the data has been processed. | [scope async]
user_data | Additional user data to pass to `func` . |

### inf_sasl_context_session_is_processing ()

    gboolean
    inf_sasl_context_session_is_processing
                                   (InfSaslContextSession *session);

Returns whether the session is currently asynchronously processing data fed to it with `inf_sasl_context_session_feed()`. In this case the first call needs to finish before another one is allowed to be made.

#### Parameters

session | A InfSaslContextSession. |

#### Returns

Whether `session` is currently processing data asynchronously.

## Types and Values

### InfSaslContext

    typedef struct _InfSaslContext InfSaslContext;

InfSaslContext is an opaque data type. You should only access it via the public API functions.

### InfSaslContextSession

    typedef struct _InfSaslContextSession InfSaslContextSession;

InfSaslContextSession represents an ongoing authentication session. Create with `inf_sasl_context_server_start_session()` or `inf_sasl_context_client_start_session()`.