27 RCSID(
"$Id: f9f8ed9a9821e19e25921bfdf5c71ef82d5cd5bf $")
29 #define LOG_PREFIX "couchbase - "
31 #include <freeradius-devel/server/base.h>
32 #include <freeradius-devel/server/map.h>
33 #include <freeradius-devel/server/module_rlm.h>
34 #include <freeradius-devel/radius/defs.h>
36 #include <freeradius-devel/json/base.h>
105 lcb_error_t cb_error = LCB_SUCCESS;
127 lcb_t cb_inst = handle->
handle;
136 if (cb_error != LCB_SUCCESS || !cookie->
jobj) {
138 RERROR(
"failed to fetch document or parse return");
146 RDEBUG3(
"parsed user document == %s", json_object_to_json_string(cookie->
jobj));
149 TALLOC_CTX *pool = talloc_pool(request, 1024);
178 if (
map_to_list_mod(pool, &vlm, request, map, NULL, NULL) < 0)
goto invalid;
209 json_object_put(cookie->
jobj);
245 lcb_error_t cb_error = LCB_SUCCESS;
255 RDEBUG2(
"could not find status type in packet");
261 status =
vp->vp_uint32;
266 RDEBUG2(
"handling accounting on/off request without action");
278 lcb_t cb_inst = handle->
handle;
300 if (cb_error != LCB_SUCCESS || cookie->
jerr != json_tokener_success || !cookie->
jobj) {
302 RERROR(
"failed to execute get request or parse returned json object");
305 json_object_put(cookie->
jobj);
309 }
else if (cookie->
jobj) {
313 RDEBUG3(
"parsed json body from couchbase: %s", json_object_to_json_string(cookie->
jobj));
319 RDEBUG2(
"no existing document found - creating new json document");
321 cookie->
jobj = json_object_new_object();
323 json_object_object_add_ex(cookie->
jobj,
"docType", json_object_new_string(
inst->doctype),
324 JSON_C_OBJECT_KEY_IS_CONSTANT);
326 json_object_object_add_ex(cookie->
jobj,
"startTimestamp", NULL, JSON_C_OBJECT_KEY_IS_CONSTANT);
327 json_object_object_add_ex(cookie->
jobj,
"stopTimestamp", NULL, JSON_C_OBJECT_KEY_IS_CONSTANT);
336 json_object_object_add_ex(cookie->
jobj,
"startTimestamp",
338 JSON_C_OBJECT_KEY_IS_CONSTANT);
346 json_object_object_add_ex(cookie->
jobj,
"stopTimestamp",
348 JSON_C_OBJECT_KEY_IS_CONSTANT);
373 RDEBUG3(
"mapped attribute %s => %s",
vp->
da->name, element);
380 if (
strlcpy(document, json_object_to_json_string(cookie->
jobj),
sizeof(document)) >=
sizeof(document)) {
382 RERROR(
"could not write json document - insufficient buffer space");
390 RDEBUG3(
"setting '%s' => '%s'", dockey, document);
396 if (cb_error != LCB_SUCCESS) {
397 RERROR(
"failed to store document (%s): %s (0x%x)", dockey, lcb_strerror(NULL, cb_error), cb_error);
403 json_object_put(cookie->
jobj);
428 if (
inst->map) json_object_put(
inst->map);
454 len = talloc_array_length(
inst->server_raw) - 1;
455 server = p = talloc_array(
inst,
char, len + 1);
456 for (i = 0; i < len; i++) {
457 switch (
inst->server_raw[i]) {
462 if (sep ==
true)
continue;
470 *p++ =
inst->server_raw[i];
476 inst->server = server;
496 ERROR(
"failed to initiate connection pool");
502 if (
inst->read_clients) {
508 ERROR(
"failed to find client section while loading clients");
516 ERROR(
"failed to find attribute subsection while loading clients");
524 DEBUG(
"preparing to load client documents");
539 INFO(
"libcouchbase version: %s", lcb_get_version(NULL));
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
static int const char char buffer[256]
#define CONF_PARSER_TERMINATOR
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
#define FR_CONF_OFFSET_FLAGS(_name, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Defines a CONF_PAIR to C data type mapping.
A section grouping multiple CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
lcb_error_t couchbase_set_key(lcb_t instance, const char *key, const char *document, int expire)
Store a document by key in Couchbase.
lcb_error_t couchbase_get_key(lcb_t instance, const void *cookie, const char *key)
Retrieve a document by key from Couchbase.
Couchbase wrapper function prototypes and datatypes.
json_object * jobj
JSON objects handled by the json-c library.
enum json_tokener_error jerr
Error values produced by the json-c library.
Information relating to the parsing of Couchbase document payloads.
#define fr_dcursor_init(_cursor, _head)
Initialise a cursor.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
#define FR_STATUS_ACCOUNTING_OFF
#define FR_STATUS_ACCOUNTING_ON
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
static bool fr_dlist_empty(fr_dlist_head_t const *list_head)
Check whether a list has any items.
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
Head of a doubly linked list.
void fr_json_version_print(void)
Print JSON-C version.
int map_list_mod_apply(request_t *request, vp_list_mod_t const *vlm)
Apply the output of map_to_list_mod to a request.
int map_to_list_mod(TALLOC_CTX *ctx, vp_list_mod_t **out, request_t *request, map_t const *map, fr_value_box_list_t *lhs_result, fr_value_box_list_t *rhs_result)
Evaluate a map creating a new map with TMPL_TYPE_ATTR LHS and TMPL_TYPE_DATA RHS.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
int mod_attribute_to_element(const char *name, json_object *map, void *buf)
Map attributes to JSON element names.
int mod_free_api_opts(rlm_couchbase_t *inst)
Delete a object built by mod_build_api_opts()
int mod_build_api_opts(CONF_SECTION *conf, rlm_couchbase_t *inst)
Build a couchbase_opts_t structure from the configuration "couchbase_api" list.
int mod_load_client_documents(rlm_couchbase_t *inst, CONF_SECTION *tmpl, CONF_SECTION *map)
Load client entries from Couchbase client documents on startup.
int mod_build_attribute_element_map(CONF_SECTION *conf, rlm_couchbase_t *inst)
Build a JSON object map from the configuration "map" list.
int mod_ensure_start_timestamp(json_object *json, fr_pair_list_t *vps)
Ensure accounting documents always contain a valid timestamp.
int mod_conn_alive(UNUSED void *opaque, void *connection)
Check the health of a connection handle.
int mod_json_object_to_map(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request, json_object *json, fr_dict_attr_t const *list)
Build value pairs from the passed JSON object and add to the request.
json_object * mod_value_pair_to_json_object(request_t *request, fr_pair_t *vp)
Convert value pairs to json objects.
Function prototypes and datatypes used in the module.
void * cookie
Couchbase cookie (cookie_u cookie_t).
void * handle
Real couchbase instance.
Couchbase instance specific information.
The main module instance.
module_instance_t const * mi
Instance of the module being instantiated.
module_instance_t * mi
Module instance to detach.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for detach calls.
Temporary structure to hold arguments for instantiation calls.
fr_pool_t * module_rlm_connection_pool_init(CONF_SECTION *module, void *opaque, fr_pool_connection_create_t c, fr_pool_connection_alive_t a, char const *log_prefix, char const *trigger_prefix, fr_pair_list_t *trigger_args)
Initialise a module specific connection pool.
module_t common
Common fields presented by all modules.
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
void fr_pool_connection_release(fr_pool_t *pool, request_t *request, void *conn)
Release a connection.
void fr_pool_free(fr_pool_t *pool)
Delete a connection pool.
void * fr_pool_connection_get(fr_pool_t *pool, request_t *request)
Reserve a connection in the connection pool.
#define is_truncated(_ret, _max)
static const conf_parser_t config[]
#define RETURN_MODULE_NOOP
#define RETURN_MODULE_RCODE(_rcode)
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_INVALID
The module considers the request invalid.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
fr_dict_attr_t const * request_attr_request
fr_dict_attr_t const * request_attr_control
fr_dict_attr_t const * request_attr_state
fr_dict_attr_t const * request_attr_reply
static void * mod_conn_create(TALLOC_CTX *ctx, void *instance, fr_time_delta_t timeout)
Create a new memcached handle.
static int mod_detach(module_detach_ctx_t const *mctx)
Detach the module.
static int mod_load(void)
fr_dict_autoload_t rlm_couchbase_dict[]
fr_dict_attr_t const * attr_acct_session_time
static fr_dict_t const * dict_radius
fr_dict_attr_autoload_t rlm_couchbase_dict_attr[]
static unlang_action_t mod_accounting(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Write accounting data to Couchbase documents.
module_rlm_t rlm_couchbase
static unlang_action_t mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
Handle authorization requests using Couchbase document data.
fr_dict_attr_t const * attr_acct_status_type
static const conf_parser_t client_config[]
Client Configuration.
static const conf_parser_t module_config[]
Module Configuration.
fr_dict_attr_t const * attr_event_timestamp
static int mod_instantiate(module_inst_ctx_t const *mctx)
Initialize the rlm_couchbase module.
static int instantiate(module_inst_ctx_t const *mctx)
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
CONF_SECTION * conf
Module's instance configuration.
void * data
Module's instance data.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Named methods exported by a module.
#define tmpl_expand(_out, _buff, _buff_len, _request, _vpt, _escape, _escape_ctx)
Expand a tmpl to a C type, using existing storage to hold variably sized types.
eap_aka_sim_process_conf_t * inst
size_t strlcpy(char *dst, char const *src, size_t siz)
Stores an attribute, a value and various bits of other data.
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
#define talloc_get_type_abort_const
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
fr_pair_t * fr_pair_list_next(fr_pair_list_t const *list, fr_pair_t const *item))
Get the next item in a valuepair list after a specific entry.