The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
rlm_couchbase.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: f9f8ed9a9821e19e25921bfdf5c71ef82d5cd5bf $
19 *
20 * @brief Integrate FreeRADIUS with the Couchbase document database.
21 * @file rlm_couchbase.c
22 *
23 * @author Aaron Hurt (ahurt@anbcs.com)
24 * @copyright 2013-2014 The FreeRADIUS Server Project.
25 */
26
27RCSID("$Id: f9f8ed9a9821e19e25921bfdf5c71ef82d5cd5bf $")
28
29#define LOG_PREFIX "couchbase - "
30
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>
35
36#include <freeradius-devel/json/base.h>
37
38#include "mod.h"
39#include "couchbase.h"
40
41/**
42 * Client Configuration
43 */
44static const conf_parser_t client_config[] = {
45 { FR_CONF_OFFSET("view", rlm_couchbase_t, client_view), .dflt = "_design/client/_view/by_name" },
47};
48
49/**
50 * Module Configuration
51 */
52static const conf_parser_t module_config[] = {
55 { FR_CONF_OFFSET("username", rlm_couchbase_t, username) },
56 { FR_CONF_OFFSET("password", rlm_couchbase_t, password) },
57
58 { FR_CONF_OFFSET("acct_key", rlm_couchbase_t, acct_key), .dflt = "radacct_%{%{Acct-Unique-Session-Id} || %{Acct-Session-Id}}", .quote = T_DOUBLE_QUOTED_STRING },
59 { FR_CONF_OFFSET("doctype", rlm_couchbase_t, doctype), .dflt = "radacct" },
60 { FR_CONF_OFFSET("expire", rlm_couchbase_t, expire), .dflt = 0 },
61
62 { FR_CONF_OFFSET("user_key", rlm_couchbase_t, user_key), .dflt = "raduser_%md5(%tolower(%{Stripped-User-Name} || %{User-Name}))", .quote = T_DOUBLE_QUOTED_STRING },
63 { FR_CONF_OFFSET("read_clients", rlm_couchbase_t, read_clients) }, /* NULL defaults to "no" */
64 { FR_CONF_POINTER("client", 0, CONF_FLAG_SUBSECTION, NULL), .subcs = (void const *) client_config },
66};
67
68static fr_dict_t const *dict_radius;
69
72 { .out = &dict_radius, .proto = "radius" },
73 { NULL }
74};
75
79
82 { .out = &attr_acct_status_type, .name = "Acct-Status-Type", .type = FR_TYPE_UINT32, .dict = &dict_radius },
83 { .out = &attr_acct_session_time, .name = "Acct-Session-Time", .type = FR_TYPE_UINT32, .dict = &dict_radius },
84 { .out = &attr_event_timestamp, .name = "Event-Timestamp", .type = FR_TYPE_DATE, .dict = &dict_radius },
85 { NULL }
86};
87
88/** Handle authorization requests using Couchbase document data
89 *
90 * Attempt to fetch the document associated with the requested user by
91 * using the deterministic key defined in the configuration. When a valid
92 * document is found it will be parsed and the containing value pairs will be
93 * injected into the request.
94 *
95 * @param[out] p_result Operation status (#rlm_rcode_t).
96 * @param[in] mctx module calling context.
97 * @param[in] request The authorization request.
98 */
99static unlang_action_t mod_authorize(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
100{
101 rlm_couchbase_t const *inst = talloc_get_type_abort_const(mctx->mi->data, rlm_couchbase_t); /* our module instance */
102 rlm_couchbase_handle_t *handle = NULL; /* connection pool handle */
103 char buffer[MAX_KEY_SIZE];
104 char const *dockey; /* our document key */
105 lcb_error_t cb_error = LCB_SUCCESS; /* couchbase error holder */
106 rlm_rcode_t rcode = RLM_MODULE_OK; /* return code */
107 ssize_t slen;
108
109 /* assert packet as not null */
110 fr_assert(request->packet != NULL);
111
112 /* attempt to build document key */
113 slen = tmpl_expand(&dockey, buffer, sizeof(buffer), request, inst->user_key, NULL, NULL);
114 if (slen < 0) RETURN_MODULE_FAIL;
115 if ((dockey == buffer) && is_truncated((size_t)slen, sizeof(buffer))) {
116 REDEBUG("Key too long, expected < " STRINGIFY(sizeof(buffer)) " bytes, got %zi bytes", slen);
118 }
119
120 /* get handle */
121 handle = fr_pool_connection_get(inst->pool, request);
122
123 /* check handle */
124 if (!handle) RETURN_MODULE_FAIL;
125
126 /* set couchbase instance */
127 lcb_t cb_inst = handle->handle;
128
129 /* set cookie */
130 cookie_t *cookie = handle->cookie;
131
132 /* fetch document */
133 cb_error = couchbase_get_key(cb_inst, cookie, dockey);
134
135 /* check error */
136 if (cb_error != LCB_SUCCESS || !cookie->jobj) {
137 /* log error */
138 RERROR("failed to fetch document or parse return");
139 /* set return */
140 rcode = RLM_MODULE_FAIL;
141 /* return */
142 goto finish;
143 }
144
145 /* debugging */
146 RDEBUG3("parsed user document == %s", json_object_to_json_string(cookie->jobj));
147
148 {
149 TALLOC_CTX *pool = talloc_pool(request, 1024); /* We need to do lots of allocs */
150 fr_dcursor_t maps;
151 map_t *map = NULL;
152 fr_dlist_head_t map_head;
153 vp_list_mod_t *vlm;
154 fr_dlist_head_t vlm_head;
155
156 fr_dcursor_init(&maps, &map_head);
157
158 /*
159 * Convert JSON data into maps
160 */
161 if ((mod_json_object_to_map(pool, &maps, request, cookie->jobj, request_attr_control) < 0) ||
162 (mod_json_object_to_map(pool, &maps, request, cookie->jobj, request_attr_reply) < 0) ||
163 (mod_json_object_to_map(pool, &maps, request, cookie->jobj, request_attr_request) < 0) ||
164 (mod_json_object_to_map(pool, &maps, request, cookie->jobj, request_attr_state) < 0)) {
165 invalid:
166 talloc_free(pool);
167 rcode = RLM_MODULE_INVALID;
168 goto finish;
169 }
170
171 fr_dlist_init(&vlm_head, vp_list_mod_t, entry);
172
173 /*
174 * Convert all the maps into list modifications,
175 * which are guaranteed to succeed.
176 */
177 while ((map = fr_dlist_next(&map_head, map))) {
178 if (map_to_list_mod(pool, &vlm, request, map, NULL, NULL) < 0) goto invalid;
179 fr_dlist_insert_tail(&vlm_head, vlm);
180 }
181
182 if (fr_dlist_empty(&vlm_head)) {
183 RDEBUG2("Nothing to update");
184 talloc_free(pool);
185 rcode = RLM_MODULE_NOOP;
186 goto finish;
187 }
188
189 /*
190 * Apply the list of modifications
191 */
192 while ((vlm = fr_dlist_next(&vlm_head, vlm))) {
193 int ret;
194
195 ret = map_list_mod_apply(request, vlm); /* SHOULD NOT FAIL */
196 if (!fr_cond_assert(ret == 0)) {
197 talloc_free(pool);
198 rcode = RLM_MODULE_FAIL;
199 goto finish;
200 }
201 }
202
203 talloc_free(pool);
204 }
205
206finish:
207 /* free json object */
208 if (cookie->jobj) {
209 json_object_put(cookie->jobj);
210 cookie->jobj = NULL;
211 }
212
213 /* release handle */
214 if (handle) fr_pool_connection_release(inst->pool, request, handle);
215
216 /* return */
217 RETURN_MODULE_RCODE(rcode);
218}
219
220/** Write accounting data to Couchbase documents
221 *
222 * Handle accounting requests and store the associated data into JSON documents
223 * in couchbase mapping attribute names to JSON element names per the module configuration.
224 *
225 * When an existing document already exists for the same accounting section the new attributes
226 * will be merged with the currently existing data. When conflicts arrise the new attribute
227 * value will replace or be added to the existing value.
228 *
229 * @param[out] p_result Result of calling the module.
230 * @param mctx module calling context.
231 * @param request The accounting request object.
232 */
233static unlang_action_t mod_accounting(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
234{
235 rlm_couchbase_t const *inst = talloc_get_type_abort_const(mctx->mi->data, rlm_couchbase_t); /* our module instance */
236 rlm_couchbase_handle_t *handle = NULL; /* connection pool handle */
237 rlm_rcode_t rcode = RLM_MODULE_OK; /* return code */
238 fr_pair_t *vp; /* radius value pair linked list */
239 char buffer[MAX_KEY_SIZE];
240 char const *dockey; /* our document key */
241 char document[MAX_VALUE_SIZE]; /* our document body */
242 char element[MAX_KEY_SIZE]; /* mapped radius attribute to element name */
243 int status = 0; /* account status type */
244 int docfound = 0; /* document found toggle */
245 lcb_error_t cb_error = LCB_SUCCESS; /* couchbase error holder */
246 ssize_t slen;
247
248
249 /* assert packet as not null */
250 fr_assert(request->packet != NULL);
251
252 /* sanity check */
253 if ((vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_acct_status_type)) == NULL) {
254 /* log debug */
255 RDEBUG2("could not find status type in packet");
256 /* return */
258 }
259
260 /* set status */
261 status = vp->vp_uint32;
262
263 /* acknowledge the request but take no action */
264 if (status == FR_STATUS_ACCOUNTING_ON || status == FR_STATUS_ACCOUNTING_OFF) {
265 /* log debug */
266 RDEBUG2("handling accounting on/off request without action");
267 /* return */
269 }
270
271 /* get handle */
272 handle = fr_pool_connection_get(inst->pool, request);
273
274 /* check handle */
275 if (!handle) RETURN_MODULE_FAIL;
276
277 /* set couchbase instance */
278 lcb_t cb_inst = handle->handle;
279
280 /* set cookie */
281 cookie_t *cookie = handle->cookie;
282
283 /* attempt to build document key */
284 slen = tmpl_expand(&dockey, buffer, sizeof(buffer), request, inst->acct_key, NULL, NULL);
285 if (slen < 0) {
286 rcode = RLM_MODULE_FAIL;
287 goto finish;
288 }
289 if ((dockey == buffer) && is_truncated((size_t)slen, sizeof(buffer))) {
290 REDEBUG("Key too long, expected < " STRINGIFY(sizeof(buffer)) " bytes, got %zi bytes", slen);
291 rcode = RLM_MODULE_FAIL;
292 /* return */
293 goto finish;
294 }
295
296 /* attempt to fetch document */
297 cb_error = couchbase_get_key(cb_inst, cookie, dockey);
298
299 /* check error and object */
300 if (cb_error != LCB_SUCCESS || cookie->jerr != json_tokener_success || !cookie->jobj) {
301 /* log error */
302 RERROR("failed to execute get request or parse returned json object");
303 /* free and reset json object */
304 if (cookie->jobj) {
305 json_object_put(cookie->jobj);
306 cookie->jobj = NULL;
307 }
308 /* check cookie json object */
309 } else if (cookie->jobj) {
310 /* set doc found */
311 docfound = 1;
312 /* debugging */
313 RDEBUG3("parsed json body from couchbase: %s", json_object_to_json_string(cookie->jobj));
314 }
315
316 /* start json document if needed */
317 if (docfound != 1) {
318 /* debugging */
319 RDEBUG2("no existing document found - creating new json document");
320 /* create new json object */
321 cookie->jobj = json_object_new_object();
322 /* set 'docType' element for new document */
323 json_object_object_add_ex(cookie->jobj, "docType", json_object_new_string(inst->doctype),
324 JSON_C_OBJECT_KEY_IS_CONSTANT);
325 /* default startTimestamp and stopTimestamp to null values */
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);
328 }
329
330 /* status specific replacements for start/stop time */
331 switch (status) {
332 case FR_STATUS_START:
333 /* add start time */
334 if ((vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_acct_status_type)) != NULL) {
335 /* add to json object */
336 json_object_object_add_ex(cookie->jobj, "startTimestamp",
338 JSON_C_OBJECT_KEY_IS_CONSTANT);
339 }
340 break;
341
342 case FR_STATUS_STOP:
343 /* add stop time */
344 if ((vp = fr_pair_find_by_da(&request->request_pairs, NULL, attr_event_timestamp)) != NULL) {
345 /* add to json object */
346 json_object_object_add_ex(cookie->jobj, "stopTimestamp",
348 JSON_C_OBJECT_KEY_IS_CONSTANT);
349 }
350 /* check start timestamp and adjust if needed */
351 mod_ensure_start_timestamp(cookie->jobj, &request->request_pairs);
352 break;
353
354 case FR_STATUS_ALIVE:
355 /* check start timestamp and adjust if needed */
356 mod_ensure_start_timestamp(cookie->jobj, &request->request_pairs);
357 break;
358
359 default:
360 /* don't doing anything */
361 rcode = RLM_MODULE_NOOP;
362 /* return */
363 goto finish;
364 }
365
366 /* loop through pairs and add to json document */
367 for (vp = fr_pair_list_head(&request->request_pairs);
368 vp;
369 vp = fr_pair_list_next(&request->request_pairs, vp)) {
370 /* map attribute to element */
371 if (mod_attribute_to_element(vp->da->name, inst->map, &element) == 0) {
372 /* debug */
373 RDEBUG3("mapped attribute %s => %s", vp->da->name, element);
374 /* add to json object with mapped name */
375 json_object_object_add(cookie->jobj, element, mod_value_pair_to_json_object(request, vp));
376 }
377 }
378
379 /* copy json string to document and check size */
380 if (strlcpy(document, json_object_to_json_string(cookie->jobj), sizeof(document)) >= sizeof(document)) {
381 /* this isn't good */
382 RERROR("could not write json document - insufficient buffer space");
383 /* set return */
384 rcode = RLM_MODULE_FAIL;
385 /* return */
386 goto finish;
387 }
388
389 /* debugging */
390 RDEBUG3("setting '%s' => '%s'", dockey, document);
391
392 /* store document/key in couchbase */
393 cb_error = couchbase_set_key(cb_inst, dockey, document, inst->expire);
394
395 /* check return */
396 if (cb_error != LCB_SUCCESS) {
397 RERROR("failed to store document (%s): %s (0x%x)", dockey, lcb_strerror(NULL, cb_error), cb_error);
398 }
399
400finish:
401 /* free and reset json object */
402 if (cookie->jobj) {
403 json_object_put(cookie->jobj);
404 cookie->jobj = NULL;
405 }
406
407 /* release our connection handle */
408 if (handle) {
409 fr_pool_connection_release(inst->pool, request, handle);
410 }
411
412 /* return */
413 RETURN_MODULE_RCODE(rcode);
414}
415
416
417/** Detach the module
418 *
419 * Detach the module instance and free any allocated resources.
420 *
421 * @param mctx The module instance.
422 * @return Returns 0 (success) in all conditions.
423 */
424static int mod_detach(module_detach_ctx_t const *mctx)
425{
426 rlm_couchbase_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_couchbase_t);
427
428 if (inst->map) json_object_put(inst->map);
429 if (inst->pool) fr_pool_free(inst->pool);
430 if (inst->api_opts) mod_free_api_opts(inst);
431
432 return 0;
433}
434
435/** Initialize the rlm_couchbase module
436 *
437 * Initialize the module and create the initial Couchbase connection pool.
438 *
439 * @param mctx The module instance.
440 * @return
441 * - 0 on success.
442 * - -1 on failure.
443 */
444static int mod_instantiate(module_inst_ctx_t const *mctx)
445{
446 rlm_couchbase_t *inst = talloc_get_type_abort(mctx->mi->data, rlm_couchbase_t); /* our module instance */
447 CONF_SECTION *conf = mctx->mi->conf;
448
449 {
450 char *server, *p;
451 size_t len, i;
452 bool sep = false;
453
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]) {
458 case '\t':
459 case ' ':
460 case ',':
461 /* Consume multiple separators occurring in sequence */
462 if (sep == true) continue;
463
464 sep = true;
465 *p++ = ';';
466 break;
467
468 default:
469 sep = false;
470 *p++ = inst->server_raw[i];
471 break;
472 }
473 }
474
475 *p = '\0';
476 inst->server = server;
477 }
478
479 /* setup item map */
481 /* fail */
482 return -1;
483 }
484
485 /* setup libcouchbase extra options */
486 if (mod_build_api_opts(conf, inst) != 0) {
487 /* fail */
488 return -1;
489 }
490
491 /* initiate connection pool */
493
494 /* check connection pool */
495 if (!inst->pool) {
496 ERROR("failed to initiate connection pool");
497 /* fail */
498 return -1;
499 }
500
501 /* load clients if requested */
502 if (inst->read_clients) {
503 CONF_SECTION *cs, *map, *tmpl; /* conf section */
504
505 /* attempt to find client section */
506 cs = cf_section_find(conf, "client", NULL);
507 if (!cs) {
508 ERROR("failed to find client section while loading clients");
509 /* fail */
510 return -1;
511 }
512
513 /* attempt to find attribute subsection */
514 map = cf_section_find(cs, "attribute", NULL);
515 if (!map) {
516 ERROR("failed to find attribute subsection while loading clients");
517 /* fail */
518 return -1;
519 }
520
521 tmpl = cf_section_find(cs, "template", NULL);
522
523 /* debugging */
524 DEBUG("preparing to load client documents");
525
526 /* attempt to load clients */
527 if (mod_load_client_documents(inst, tmpl, map) != 0) {
528 /* fail */
529 return -1;
530 }
531 }
532
533 /* return okay */
534 return 0;
535}
536
537static int mod_load(void)
538{
539 INFO("libcouchbase version: %s", lcb_get_version(NULL));
541 return 0;
542}
543
544/*
545 * Hook into the FreeRADIUS module system.
546 */
549 .common = {
550 .magic = MODULE_MAGIC_INIT,
551 .name = "couchbase",
552 .inst_size = sizeof(rlm_couchbase_t),
554 .onload = mod_load,
556 .detach = mod_detach
557 },
558 .method_group = {
559 .bindings = (module_method_binding_t[]){
560 { .section = SECTION_NAME("accounting", CF_IDENT_ANY), .method = mod_accounting },
561 { .section = SECTION_NAME("recv", CF_IDENT_ANY), .method = mod_authorize },
563 }
564 }
565};
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
Definition action.h:35
static int const char char buffer[256]
Definition acutest.h:576
#define RCSID(id)
Definition build.h:483
#define STRINGIFY(x)
Definition build.h:197
#define CONF_PARSER_TERMINATOR
Definition cf_parse.h:642
#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
Definition cf_parse.h:268
fr_token_t quote
Quoting around the default value. Only used for templates.
Definition cf_parse.h:634
#define FR_CONF_POINTER(_name, _type, _flags, _res_p)
conf_parser_t which parses a single CONF_PAIR producing a single global result
Definition cf_parse.h:323
#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
Definition cf_parse.h:256
@ CONF_FLAG_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition cf_parse.h:418
@ CONF_FLAG_SUBSECTION
Instead of putting the information into a configuration structure, the configuration file routines MA...
Definition cf_parse.h:412
Defines a CONF_PAIR to C data type mapping.
Definition cf_parse.h:579
A section grouping multiple CONF_PAIR.
Definition cf_priv.h:101
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
Definition cf_util.c:1028
#define CF_IDENT_ANY
Definition cf_util.h:78
lcb_error_t couchbase_set_key(lcb_t instance, const char *key, const char *document, int expire)
Store a document by key in Couchbase.
Definition couchbase.c:288
lcb_error_t couchbase_get_key(lcb_t instance, const void *cookie, const char *key)
Retrieve a document by key from Couchbase.
Definition couchbase.c:325
Couchbase wrapper function prototypes and datatypes.
json_object * jobj
JSON objects handled by the json-c library.
Definition couchbase.h:45
enum json_tokener_error jerr
Error values produced by the json-c library.
Definition couchbase.h:47
Information relating to the parsing of Couchbase document payloads.
Definition couchbase.h:44
#define fr_dcursor_init(_cursor, _head)
Initialise a cursor.
Definition dcursor.h:732
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition debug.h:139
#define FR_STATUS_STOP
Definition defs.h:137
#define FR_STATUS_START
Definition defs.h:136
#define FR_STATUS_ALIVE
Definition defs.h:138
#define FR_STATUS_ACCOUNTING_OFF
Definition defs.h:140
#define FR_STATUS_ACCOUNTING_ON
Definition defs.h:139
#define ERROR(fmt,...)
Definition dhcpclient.c:41
#define DEBUG(fmt,...)
Definition dhcpclient.c:39
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition dict.h:268
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition dict.h:281
Specifies an attribute which must be present for the module to function.
Definition dict.h:267
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition dict.h:280
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
Definition dl_module.h:63
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
Definition dlist.h:260
static bool fr_dlist_empty(fr_dlist_head_t const *list_head)
Check whether a list has any items.
Definition dlist.h:501
static int fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the tail of a list.
Definition dlist.h:378
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
Definition dlist.h:555
Head of a doubly linked list.
Definition dlist.h:51
void fr_json_version_print(void)
Print JSON-C version.
Definition json.c:459
#define RDEBUG3(fmt,...)
Definition log.h:343
#define RERROR(fmt,...)
Definition log.h:298
talloc_free(reap)
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.
Definition map_async.c:922
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.
Definition map_async.c:251
A list modification.
Definition map.h:99
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
long int ssize_t
int mod_attribute_to_element(const char *name, json_object *map, void *buf)
Map attributes to JSON element names.
Definition mod.c:311
int mod_free_api_opts(rlm_couchbase_t *inst)
Delete a object built by mod_build_api_opts()
Definition mod.c:63
int mod_build_api_opts(CONF_SECTION *conf, rlm_couchbase_t *inst)
Build a couchbase_opts_t structure from the configuration "couchbase_api" list.
Definition mod.c:93
int mod_load_client_documents(rlm_couchbase_t *inst, CONF_SECTION *tmpl, CONF_SECTION *map)
Load client entries from Couchbase client documents on startup.
Definition mod.c:706
int mod_build_attribute_element_map(CONF_SECTION *conf, rlm_couchbase_t *inst)
Build a JSON object map from the configuration "map" list.
Definition mod.c:237
int mod_ensure_start_timestamp(json_object *json, fr_pair_list_t *vps)
Ensure accounting documents always contain a valid timestamp.
Definition mod.c:604
int mod_conn_alive(UNUSED void *opaque, void *connection)
Check the health of a connection handle.
Definition mod.c:208
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.
Definition mod.c:373
void * mod_conn_create(TALLOC_CTX *ctx, void *instance, fr_time_delta_t timeout)
Create a new connection pool handle.
Definition mod.c:154
json_object * mod_value_pair_to_json_object(request_t *request, fr_pair_t *vp)
Convert value pairs to json objects.
Definition mod.c:510
Function prototypes and datatypes used in the module.
#define MAX_VALUE_SIZE
Definition mod.h:35
void * cookie
Couchbase cookie (cookie_u cookie_t).
Definition mod.h:73
#define MAX_KEY_SIZE
Definition mod.h:38
void * handle
Real couchbase instance.
Definition mod.h:72
Couchbase instance specific information.
Definition mod.h:71
The main module instance.
Definition mod.h:44
module_instance_t const * mi
Instance of the module being instantiated.
Definition module_ctx.h:42
module_instance_t * mi
Module instance to detach.
Definition module_ctx.h:57
module_instance_t * mi
Instance of the module being instantiated.
Definition module_ctx.h:51
Temporary structure to hold arguments for module calls.
Definition module_ctx.h:41
Temporary structure to hold arguments for detach calls.
Definition module_ctx.h:56
Temporary structure to hold arguments for instantiation calls.
Definition module_ctx.h:50
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.
Definition module_rlm.c:308
module_t common
Common fields presented by all modules.
Definition module_rlm.h:39
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.
Definition pair.c:693
void fr_pool_connection_release(fr_pool_t *pool, request_t *request, void *conn)
Release a connection.
Definition pool.c:1407
void fr_pool_free(fr_pool_t *pool)
Delete a connection pool.
Definition pool.c:1329
void * fr_pool_connection_get(fr_pool_t *pool, request_t *request)
Reserve a connection in the connection pool.
Definition pool.c:1392
#define is_truncated(_ret, _max)
Definition print.h:48
static const conf_parser_t config[]
Definition base.c:183
#define fr_assert(_expr)
Definition rad_assert.h:38
#define REDEBUG(fmt,...)
Definition radclient.h:52
#define RDEBUG2(fmt,...)
Definition radclient.h:54
#define INFO(fmt,...)
Definition radict.c:54
static rs_t * conf
Definition radsniff.c:53
#define RETURN_MODULE_NOOP
Definition rcode.h:62
#define RETURN_MODULE_RCODE(_rcode)
Definition rcode.h:64
#define RETURN_MODULE_OK
Definition rcode.h:57
#define RETURN_MODULE_FAIL
Definition rcode.h:56
rlm_rcode_t
Return codes indicating the result of the module call.
Definition rcode.h:40
@ RLM_MODULE_INVALID
The module considers the request invalid.
Definition rcode.h:45
@ RLM_MODULE_OK
The module is OK, continue.
Definition rcode.h:43
@ RLM_MODULE_FAIL
Module failed, don't reply.
Definition rcode.h:42
@ RLM_MODULE_NOOP
Module succeeded without doing anything.
Definition rcode.h:48
fr_dict_attr_t const * request_attr_request
Definition request.c:45
fr_dict_attr_t const * request_attr_control
Definition request.c:47
fr_dict_attr_t const * request_attr_state
Definition request.c:48
fr_dict_attr_t const * request_attr_reply
Definition request.c:46
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)
Definition rlm_rest.c:1310
username
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
Definition section.h:40
CONF_SECTION * conf
Module's instance configuration.
Definition module.h:329
size_t inst_size
Size of the module's instance data.
Definition module.h:203
void * data
Module's instance data.
Definition module.h:271
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Definition module.h:151
Named methods exported by a module.
Definition module.h:173
#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.
Definition tmpl.h:1060
eap_aka_sim_process_conf_t * inst
fr_pair_t * vp
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition strlcpy.c:34
Value pair map.
Definition map.h:77
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
fr_dict_attr_t const *_CONST da
Dictionary attribute defines the attribute number, vendor and type of the pair.
Definition pair.h:69
#define talloc_get_type_abort_const
Definition talloc.h:282
@ T_DOUBLE_QUOTED_STRING
Definition token.h:121
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.
Definition pair_inline.c:70
fr_pair_t * fr_pair_list_head(fr_pair_list_t const *list)
Get the head of a valuepair list.
Definition pair_inline.c:43