## prelude-client

prelude-client — Creating a Prelude Client

## Synopsis

    enum        prelude_client_exit_status_t;
    enum        prelude_client_flags_t;
    typedef     prelude_client_t;
    prelude_ident_t* prelude_client_get_unique_ident
                                                (prelude_client_t *client);
    void        prelude_client_set_connection_pool
                                                (prelude_client_t *client,
                                                 prelude_connection_pool_t *pool);
    prelude_connection_pool_t* prelude_client_get_connection_pool
                                                (prelude_client_t *client);
    int         prelude_client_start            (prelude_client_t *client);
    int         prelude_client_init             (prelude_client_t *client);
    int         prelude_client_new              (prelude_client_t **client,
                                                 const char *profile);
    idmef_analyzer_t* prelude_client_get_analyzer
                                                (prelude_client_t *client);
    prelude_client_flags_t prelude_client_get_flags
                                                (prelude_client_t *client);
    void        prelude_client_set_required_permission
                                                (prelude_client_t *client,
                                                 prelude_connection_permission_t permission);
    prelude_connection_permission_t prelude_client_get_required_permission
                                                (prelude_client_t *client);
    void        prelude_client_send_msg         (prelude_client_t *client,
                                                 prelude_msg_t *msg);
    void        prelude_client_set_heartbeat_cb (prelude_client_t *client,
                                                 void (*cb) (prelude_client_t *client, idmef_message_t *hb));
    void        prelude_client_send_idmef       (prelude_client_t *client,
                                                 idmef_message_t *msg);
    void        prelude_client_destroy          (prelude_client_t *client,
                                                 prelude_client_exit_status_t status);
    int         prelude_client_set_flags        (prelude_client_t *client,
                                                 prelude_client_flags_t flags);
    int         prelude_client_set_config_filename
                                                (prelude_client_t *client,
                                                 const char *filename);
    const char* prelude_client_get_config_filename
                                                (prelude_client_t *client);
    prelude_bool_t prelude_client_is_setup_needed
                                                (int error);
    prelude_client_profile_t* prelude_client_get_profile
                                                (prelude_client_t *client);
    int         prelude_client_new_msgbuf       (prelude_client_t *client,
                                                 prelude_msgbuf_t **msgbuf);
    int         prelude_client_handle_msg_default
                                                (prelude_client_t *client,
                                                 prelude_msg_t *msg,
                                                 prelude_msgbuf_t *msgbuf);
    const char* prelude_client_get_setup_error  (prelude_client_t *client);
    void        prelude_client_print_setup_error
                                                (prelude_client_t *client);

## Description

In order to send or to read data from a Prelude collector (prelude-manager), you will need to create a prelude_client_t object. This object will be necessary for most of the work you are going to do with prelude.

## Creating the client

    int ret;
    prelude_client_t *client;

    ret = prelude_client_new(&client, "my-analyzer");
    if ( ! client ) {
            prelude_perror(ret, "Unable to create a prelude client object");
            return -1;
    }

This will create a new client object, whose default profile is my-analyzer. This default profile might be overriden using the --prelude --profile profile_name option on your command line as parsed by `prelude_init()`.

Additionally, prelude specific option might be overriden using a Prelude specific configuration file, like the template file created within each profile, or a configuration file specified using `prelude_client_set_config_filename()` before `prelude_client_start()` is called.

The default required permission for the created client are set to PRELUDE_CONNECTION_PERMISSION_IDMEF_WRITE and PRELUDE_CONNECTION_PERMISSION_ADMIN_READ, which mean the client will reject any certificate where permission are set to anything less than this. You can change the default required permission using the `prelude_client_set_required_permission()` function.

As an example, if you want to create a client that will read alert from a Manager, and accept administrative option request you should use:

    prelude_client_set_required_permission(client, PRELUDE_CONNECTION_PERMISSION_IDMEF_READ|PRELUDE_CONNECTION_PERMISSION_ADMIN_WRITE);

Once the client is created and you have everything setup, you will need to start your client. The `prelude_client_start()` function is responsible for this, and will trigger the connection to the configured manager, and send the initial client heartbeat.

    ret = prelude_client_start(client);
    if ( ret < 0 ) {
           prelude_log(ret, "Unable to start prelude client");
           return -1;
    }

Additionally, it is possible to set additional client flags, however, you should be careful since some of theses flags (marked asynchronous) will result in creating an internal thread, which should only be done after an eventual fork of the program since threads are not copied accross a fork call.

The prelude library will also register an internal timer in order to send heartbeat message at the defined interval. Timer registered by the library itself or by the program will either be called automatically if the PRELUDE_CLIENT_FLAGS_ASYNC_TIMER flags is set, otherwise, the program is responsible for calling the `prelude_timer_wake_up()` function every second from it's main loop, in order to check the registered timer.

- PRELUDE_CLIENT_FLAGS_CONNECT - Used for a client to connect to a manager (this is the default).
- PRELUDE_CLIENT_FLAGS_HEARTBEAT - Used for client to send heartbeat (this is the default).
- PRELUDE_CLIENT_FLAGS_ASYNC_SEND - Used if you want message to be sent asynchronously.
- PRELUDE_CLIENT_FLAGS_ASYNC_TIMER - Used if you want timer to be automatically called from the asynchronous thread.
- See prelude_client_flags_t for a list of available flags.

    ret = prelude_client_set_flags(client, PRELUDE_CLIENT_FLAGS_ASYNC_SEND|PRELUDE_CLIENT_FLAGS_ASYNC_TIMER);
    if ( ret < 0 ) {
           fprintf(stderr, "Unable to set asynchronous send and timer.\n");
           return -1;
    }

## Sending IDMEF message

For documentation on how to create IDMEF message, please see idmef_message_t or idmef_path_t.

Once you created and IDMEF message, you should use the `prelude_client_send_idmef()` function in order to send it to the collector you are connected to.

    prelude_client_send_idmef(client, idmef);

## Destroying the client

In case the analyzer you are developing is not a persistant analyzer (meaning an analyzer that is not supposed to exit), it is important that you call the `prelude_client_destroy()` function prior to exiting. This function have the side effect of sending an heartbeat to the remote manager, as well as an information regarding the analyzer state.

This state information is important since an analyzer not reporting a successful exit status, or an analyzer which stop sending heartbeat at all will be reported as having a problem.

- PRELUDE_CLIENT_STATUS_EXIT_SUCCESS - Exiting the sensor is the expected behavior.
- PRELUDE_CLIENT_STATUS_EXIT_FAILED - There is something wrong going on, notice the security analyst.

    prelude_client_destroy(client, PRELUDE_CLIENT_STATUS_EXIT_SUCCESS);

As a side note, please remember that a persistant sensor should never use this function (except maybe if it is working in batch mode), unless it want to report the PRELUDE_CLIENT_STATUS_EXIT_FAILED exit status. This is also the case if your persistant sensor is interrupted by a signal.

## Details

### enum prelude_client_exit_status_t

    typedef enum {
            PRELUDE_CLIENT_EXIT_STATUS_SUCCESS = 0,
            PRELUDE_CLIENT_EXIT_STATUS_FAILURE = -1
    } prelude_client_exit_status_t;

### enum prelude_client_flags_t

    typedef enum {
            PRELUDE_CLIENT_FLAGS_ASYNC_SEND  = 0x01,
            PRELUDE_CLIENT_FLAGS_ASYNC_TIMER = 0x02,
            PRELUDE_CLIENT_FLAGS_HEARTBEAT   = 0x04,
            PRELUDE_CLIENT_FLAGS_CONNECT     = 0x08
    } prelude_client_flags_t;

### prelude_client_t

    typedef struct prelude_client prelude_client_t;

### prelude_client_get_unique_ident ()

    prelude_ident_t* prelude_client_get_unique_ident
                                                (prelude_client_t *client);

`client` : |
Returns : |

### prelude_client_set_connection_pool ()

    void        prelude_client_set_connection_pool
                                                (prelude_client_t *client,
                                                 prelude_connection_pool_t *pool);

Use this function in order to set your own list of peer that `client` should send message too. This might be usefull in case you don't want this to be automated by `prelude_client_init()`.

`client` : | pointer to a prelude_client_t object.
`pool` : | pointer to a prelude_client_pool_t object.

### prelude_client_get_connection_pool ()

    prelude_connection_pool_t* prelude_client_get_connection_pool
                                                (prelude_client_t *client);

Return a pointer to the prelude_connection_pool_t object used by `client` to send messages.

`client` : | pointer to a prelude_client_t object.
Returns : | a pointer to a prelude_connection_pool_t object.

### prelude_client_start ()

    int         prelude_client_start            (prelude_client_t *client);

This function start the `client` object, triggering a connection from the client to it's server if any were specified, and sending the initial `client` heartbeat.

If `client` was not initialized, then `prelude_client_init()` will be called and thus this function might fail if the client was not registered.

`client` : | Pointer to a client object to initialize.
Returns : | 0 on success, -1 if an error occured.

### prelude_client_init ()

    int         prelude_client_init             (prelude_client_t *client);

This function initialize the `client` object, meaning reading generic options from the `prelude_client_new()` provided configuration file and the array of arguments specified through `prelude_init()`.

Calling this function is optional and should be done only if you need more granularity between `prelude_client_new()` and `prelude_client_start()`:

`prelude_client_start()` will call `prelude_client_init()` for you if needed.

`client` : | Pointer to a prelude_client_t object to initialize.
Returns : | 0 on success, -1 if an error occured.

### prelude_client_new ()

    int         prelude_client_new              (prelude_client_t **client,
                                                 const char *profile);

This function initialize the `client` object.

`client` : | Pointer to a client object to initialize.
`profile` : | Default profile name for this analyzer.
Returns : | 0 on success or a negative value if an error occur.

### prelude_client_get_analyzer ()

    idmef_analyzer_t* prelude_client_get_analyzer
                                                (prelude_client_t *client);

Provide access to the idmef_analyzer_t object associated to `client`. This analyzer object is sent along with every alerts and heartbeats emited by this client. The analyzer object is created by `prelude_client_init()`.

`client` : | Pointer to a prelude_client_t object.
Returns : | the idmef_analyzer_t object associated with `client`.

### prelude_client_get_flags ()

    prelude_client_flags_t prelude_client_get_flags
                                                (prelude_client_t *client);

Get flags set through `prelude_client_set_flags()`.

`client` : | Pointer on a prelude_client_t object.
Returns : | an or'ed list of prelude_client_flags_t.

### prelude_client_set_required_permission ()

    void        prelude_client_set_required_permission
                                                (prelude_client_t *client,
                                                 prelude_connection_permission_t permission);

Set the required `permission` for `client`. The default is PRELUDE_CONNECTION_PERMISSION_IDMEF_WRITE | PRELUDE_CONNECTION_PERMISSION_ADMIN_READ. Value set through this function should be set before `prelude_client_start()`.

If the client certificate for connecting to one of the specified manager doesn't have theses permission the client will reject the certificate and ask for registration.

`client` : | Pointer on a prelude_client_t object.
`permission` : | Required permission for `client`.

### prelude_client_get_required_permission ()

    prelude_connection_permission_t prelude_client_get_required_permission
                                                (prelude_client_t *client);

`client` : | Pointer on a prelude_client_t object.
Returns : | `client` permission as set with `prelude_client_set_required_permission()`

### prelude_client_send_msg ()

    void        prelude_client_send_msg         (prelude_client_t *client,
                                                 prelude_msg_t *msg);

Send `msg` to the peers `client` is communicating with.

The message will be sent asynchronously if `PRELUDE_CLIENT_FLAGS_ASYNC_SEND` was set using `prelude_client_set_flags()` in which case the caller should not call `prelude_msg_destroy()` on `msg`.

`client` : | Pointer to a prelude_client_t object.
`msg` : | pointer to a message that `client` should send.

### prelude_client_set_heartbeat_cb ()

    void        prelude_client_set_heartbeat_cb (prelude_client_t *client,
                                                 void (*cb) (prelude_client_t *client, idmef_message_t *hb));

Use if you want to override the default function used to automatically send heartbeat to `client` peers.

`client` : | pointer to a prelude_client_t object.
`cb` : | pointer to a function handling heartbeat sending.

### prelude_client_send_idmef ()

    void        prelude_client_send_idmef       (prelude_client_t *client,
                                                 idmef_message_t *msg);

Send `msg` to the peers `client` is communicating with.

The message will be sent asynchronously if `PRELUDE_CLIENT_FLAGS_ASYNC_SEND` was set using `prelude_client_set_flags()`.

`client` : | Pointer to a prelude_client_t object.
`msg` : | pointer to an IDMEF message to be sent to `client` peers.

### prelude_client_destroy ()

    void        prelude_client_destroy          (prelude_client_t *client,
                                                 prelude_client_exit_status_t status);

Destroy `client`, and send an heartbeat containing the 'exiting' status in case `status` is PRELUDE_CLIENT_EXIT_STATUS_SUCCESS.

This is useful for analyzer expected to be running periodically, and that shouldn't be treated as behaving anormaly in case no heartbeat is sent.

Please note that your are not supposed to run this function from a signal handler.

`client` : | Pointer on a client object.
`status` : | Exit status for the client.

### prelude_client_set_flags ()

    int         prelude_client_set_flags        (prelude_client_t *client,
                                                 prelude_client_flags_t flags);

Set specific flags in the `client` structure. This function can be called anytime after the creation of the `client` object.

When settings asynchronous flags such as PRELUDE_CLIENT_FLAGS_ASYNC_SEND or PRELUDE_CLIENT_FLAGS_ASYNC_TIMER, be carefull to call `prelude_client_set_flags()` in the same process you want to use the asynchronous API from. Threads aren't copied accross `fork()`.

`client` : | Pointer on a prelude_client_t object.
`flags` : | Or'd list of flags used by `client`.
Returns : | 0 if setting `flags` succeed, -1 otherwise.

### prelude_client_set_config_filename ()

    int         prelude_client_set_config_filename
                                                (prelude_client_t *client,
                                                 const char *filename);

The default for a client is to use a template configuration file (idmef-client.conf). By using this function you might override the default and provide your own configuration file to use for `client`. The format of the configuration file need to be compatible with the Prelude format.

`client` : | pointer on a prelude_client_t object.
`filename` : | Configuration file to use for this client.
Returns : | 0 on success, -1 if an error occured.

### prelude_client_get_config_filename ()

    const char* prelude_client_get_config_filename
                                                (prelude_client_t *client);

Return the filename where `client` configuration is stored. This filename is originally set by the `prelude_client_new()` function.

`client` : | pointer on a prelude_client_t object.
Returns : | a pointer to `client` configuration filename.

### prelude_client_is_setup_needed ()

    prelude_bool_t prelude_client_is_setup_needed
                                                (int error);

### Warning

`prelude_client_is_setup_needed` is deprecated and should not be used in newly-written code. use standard error API.

This function should be called as a result of an error by the `prelude_client_start()` function, to know if the analyzer need to be registered.

Returns:

`error` : | Error returned by `prelude_client_start()`.
Returns : | TRUE if setup is needed, FALSE otherwise.

### prelude_client_get_profile ()

    prelude_client_profile_t* prelude_client_get_profile
                                                (prelude_client_t *client);

`client` : |
Returns : |

### prelude_client_new_msgbuf ()

    int         prelude_client_new_msgbuf       (prelude_client_t *client,
                                                 prelude_msgbuf_t **msgbuf);

`client` : |
`msgbuf` : |
Returns : |

### prelude_client_handle_msg_default ()

    int         prelude_client_handle_msg_default
                                                (prelude_client_t *client,
                                                 prelude_msg_t *msg,
                                                 prelude_msgbuf_t *msgbuf);

`client` : |
`msg` : |
`msgbuf` : |
Returns : |

### prelude_client_get_setup_error ()

    const char* prelude_client_get_setup_error  (prelude_client_t *client);

`client` : |
Returns : |

### prelude_client_print_setup_error ()

    void        prelude_client_print_setup_error
                                                (prelude_client_t *client);

`client` : |

## See Also

idmef_message_t idmef_path_t