27 RCSID(
"$Id: e2008e764a8d28c48a3944d7a4604149d02856e9 $")
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.
void *_CONST data
Module instance's parsed configuration.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
CONF_SECTION *_CONST conf
Module's instance configuration.
dl_module_inst_t const * inst
#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.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
Specifies a module method identifier.
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)
@ MODULE_TYPE_THREAD_SAFE
Module is threadsafe.
#define MODULE_NAME_TERMINATOR
#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.