#include <freeradius-devel/rad_assert.h>
#include <libcouchbase/couchbase.h>
-#include <json/json.h>
+#include <json.h>
#include "mod.h"
#include "couchbase.h"
* Module Configuration
*/
static const CONF_PARSER module_config[] = {
- {"acctkey", PW_TYPE_STRING_PTR, offsetof(rlm_couchbase_t, acctkey), NULL,
- "radacct_%{%{Acct-Unique-Session-Id}:-%{Acct-Session-Id}}"},
- {"doctype", PW_TYPE_STRING_PTR, offsetof(rlm_couchbase_t, doctype), NULL, "radacct"},
- {"server", PW_TYPE_STRING_PTR | PW_TYPE_REQUIRED, offsetof(rlm_couchbase_t, server), NULL, NULL},
- {"bucket", PW_TYPE_STRING_PTR | PW_TYPE_REQUIRED, offsetof(rlm_couchbase_t, bucket), NULL, NULL},
- {"pass", PW_TYPE_STRING_PTR, offsetof(rlm_couchbase_t, pass), NULL, NULL},
- {"expire", PW_TYPE_INTEGER, offsetof(rlm_couchbase_t, expire), NULL, 0},
- {"userkey", PW_TYPE_STRING_PTR | PW_TYPE_REQUIRED, offsetof(rlm_couchbase_t, userkey), NULL,
- "raduser_%{md5:%{tolower:%{%{Stripped-User-Name}:-%{User-Name}}}}"},
+ { "acct_key", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_couchbase_t, acct_key), "radacct_%{%{Acct-Unique-Session-Id}:-%{Acct-Session-Id}}" },
+ { "doctype", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_couchbase_t, doctype), "radacct" },
+ { "server", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_REQUIRED, rlm_couchbase_t, server_raw), NULL },
+ { "bucket", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_REQUIRED, rlm_couchbase_t, bucket), NULL },
+ { "password", FR_CONF_OFFSET(PW_TYPE_STRING, rlm_couchbase_t, password), NULL },
+ { "expire", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_couchbase_t, expire), 0 },
+ { "user_key", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_REQUIRED, rlm_couchbase_t, user_key), "raduser_%{md5:%{tolower:%{%{Stripped-User-Name}:-%{User-Name}}}}" },
{NULL, -1, 0, NULL, NULL} /* end the list */
};
/* initialize couchbase connection */
static int mod_instantiate(CONF_SECTION *conf, void *instance) {
+ static bool version_done;
+
rlm_couchbase_t *inst = instance; /* our module instance */
- /* fail on bad config */
- if (cf_section_parse(conf, inst, module_config) < 0) {
- ERROR("rlm_couchbase: failed to parse config");
- /* fail */
- return -1;
+ if (!version_done) {
+ version_done = true;
+ INFO("rlm_couchbase: json-c version: %s", json_c_version());
+ INFO("rlm_couchbase: libcouchbase version: %s", lcb_get_version(NULL));
}
- /* rebuild server list if needed - libcouchbase only takes a semi-colon separated list */
- if (strchr(inst->server, '\t') || strchr(inst->server, ' ') || strchr(inst->server, ',')) {
- char *tok; /* temporary token pointer */
- /* make a temporary copy of the server string */
- char *temps1 = talloc_typed_strdup(inst, inst->server);
- /* temporary buffer for the new server string */
- char *temps2 = talloc_zero_size(inst, strlen(inst->server) + 1);
- /* loop through server list and break into pieces */
- while ((tok = strsep(&temps1, "\t ,")) != NULL) {
- /* build server string */
- if (strlen(tok)) {
- temps2 = talloc_asprintf_append(temps2, "%s;", tok);
+ {
+ char *server, *p;
+ size_t len, i;
+ bool sep = false;
+
+ len = talloc_array_length(inst->server_raw);
+ server = p = talloc_array(inst, char, len);
+ for (i = 0; i < len; i++) {
+ switch (inst->server_raw[i]) {
+ case '\t':
+ case ' ':
+ case ',':
+ /* Consume multiple separators occurring in sequence */
+ if (sep == true) continue;
+
+ sep = true;
+ *p++ = ';';
+ break;
+
+ default:
+ sep = false;
+ *p++ = inst->server_raw[i];
+ break;
}
}
- /* replace old server string with new */
- strlcpy(inst->server, temps2, strlen(temps2));
- /* free temporary buffers */
- talloc_free(temps1);
- talloc_free(temps2);
- /* debugging */
- DEBUG("rlm_couchbase: built server string '%s' from config", inst->server);
+
+ *p = '\0';
+ inst->server = server;
}
/* setup item map */
}
/* initiate connection pool */
- inst->pool = fr_connection_pool_init(conf, inst, mod_conn_create, mod_conn_alive, mod_conn_delete, NULL);
+ inst->pool = fr_connection_pool_init(conf, inst, mod_conn_create, mod_conn_alive, NULL);
/* check connection pool */
if (!inst->pool) {
rad_assert(request->packet != NULL);
/* attempt to build document key */
- if (radius_xlat(dockey, sizeof(dockey), request, inst->userkey, NULL, NULL) < 0) {
+ if (radius_xlat(dockey, sizeof(dockey), request, inst->user_key, NULL, NULL) < 0) {
/* log error */
- RERROR("could not find user key attribute (%s) in packet", inst->userkey);
+ RERROR("could not find user key attribute (%s) in packet", inst->user_key);
/* return */
return RLM_MODULE_FAIL;
}
}
/* attempt to build document key */
- if (radius_xlat(dockey, sizeof(dockey), request, inst->acctkey, NULL, NULL) < 0) {
+ if (radius_xlat(dockey, sizeof(dockey), request, inst->acct_key, NULL, NULL) < 0) {
/* log error */
- RERROR("could not find accounting key attribute (%s) in packet", inst->acctkey);
+ RERROR("could not find accounting key attribute (%s) in packet", inst->acct_key);
/* release handle */
if (handle) {
fr_connection_release(inst->pool, handle);
}
/* check start timestamp and adjust if needed */
mod_ensure_start_timestamp(cookie->jobj, request->packet->vps);
+ break;
case PW_STATUS_ALIVE:
/* check start timestamp and adjust if needed */
mod_ensure_start_timestamp(cookie->jobj, request->packet->vps);
}
/* return without doing anything */
return RLM_MODULE_NOOP;
- break;
}
/* loop through pairs and add to json document */