* @see json_pairmake_leaf
*/
typedef struct json_flags {
- boolean do_xlat; //!< If TRUE value will be expanded with xlat.
- boolean is_json; //!< If TRUE value will be inserted as raw JSON
+ int do_xlat; //!< If TRUE value will be expanded with xlat.
+ int is_json; //!< If TRUE value will be inserted as raw JSON
// (multiple values not supported).
FR_TOKEN op; //!< The operator that determines how the new VP
// is processed. @see fr_tokens
long last_socket;
CURLcode ret;
- curl_easy_getinfo(candle, CURLINFO_LASTSOCKET, &last_socket);
+ ret = curl_easy_getinfo(candle, CURLINFO_LASTSOCKET, &last_socket);
if (ret != CURLE_OK) {
radlog(L_ERR,
"rlm_rest (%s): Couldn't determine socket"
goto end_chunk;
}
- RDEBUG2("Encoding attribute \"%s\"", current[0]->name);
+ RDEBUG2("Encoding attribute \"%s\"", current[0]->da->name);
if (ctx->state == READ_STATE_ATTR_BEGIN) {
- escaped = curl_escape(current[0]->name,
- strlen(current[0]->name));
+ escaped = curl_escape(current[0]->da->name,
+ strlen(current[0]->da->name));
len = strlen(escaped);
if (s < (1 + len)) {
* New attribute, write name, type, and beginning of
* value array.
*/
- RDEBUG2("Encoding attribute \"%s\"", current[0]->name);
+ RDEBUG2("Encoding attribute \"%s\"", current[0]->da->name);
if (ctx->state == READ_STATE_ATTR_BEGIN) {
- type = fr_int2str(dict_attr_types, current[0]->type,
+ type = fr_int2str(dict_attr_types, current[0]->da->type,
"¿Unknown?");
len = strlen(type);
- len += strlen(current[0]->name);
+ len += strlen(current[0]->da->name);
if (s < (23 + len)) goto no_space;
len = sprintf(p, "\"%s\":{\"type\":\"%s\",\"value\":[" ,
- current[0]->name, type);
+ current[0]->da->name, type);
p += len;
s -= len;
/*
* Multivalued attribute
*/
- if (current[1] &&
- ((current[0]->attribute == current[1]->attribute) &&
- (current[0]->vendor == current[1]->vendor))) {
+ if (current[1] &&
+ (current[0]->da == current[1]->da)) {
*p++ = ',';
current++;
/* TODO: Quicksort would be faster... */
do {
for(i = 1; i < count; i++) {
- assert(current[i-1]->attribute &&
- current[i]->attribute);
-
swap = 0;
- if ((current[i-1]->vendor > current[i]->vendor) ||
- ((current[i-1]->vendor == current[i]->vendor) &&
- (current[i-1]->attribute > current[i]->attribute)
- )) {
+ if (current[i-1]->da > current[i]->da) {
tmp = current[i];
current[i] = current[i-1];
current[i-1] = tmp;
}
}
-/** Verify that value wasn't truncated when it was converted to a VALUE_PAIR
- *
- * Certain values may be truncated when they're converted into VALUE_PAIRs
- * for example 64bit integers converted to 32bit integers. Warn the user
- * when this happens.
- *
- * @param[in] request Current request.
- * @param[in] raw string from decoder.
- * @param[in] vp containing parsed value.
- */
-static void rest_check_truncation(REQUEST *request, const char *raw,
- VALUE_PAIR *vp)
-{
- char cooked[1024];
-
- vp_prints_value(cooked, sizeof(cooked), vp, 0);
- if (strcmp(raw, cooked) != 0) {
- RDEBUG("WARNING: Value-Pair does not match POST value, "
- "truncation may have occurred");
- RDEBUG("\tValue (pair) : \"%s\"", cooked);
- RDEBUG("\tValue (post) : \"%s\"", raw);
- }
-}
-
/** Converts POST response into VALUE_PAIRs and adds them to the request
*
* Accepts VALUE_PAIRS in the same format as rest_encode_post, but with the
const char *attribute;
char *name = NULL;
char *value = NULL;
+
+ char buffer[1024];
const DICT_ATTR *da;
VALUE_PAIR *vp;
const DICT_ATTR **current, *processed[REST_BODY_MAX_ATTRS + 1];
- VALUE_PAIR *tmp;
pair_lists_t list_name;
request_refs_t request_name;
request_name = radius_request_name(&attribute, REQUEST_CURRENT);
if (request_name == REQUEST_UNKNOWN) {
- RDEBUG("WARNING: Invalid request qualifier, skipping");
+ RDEBUGW("Invalid request qualifier, skipping");
curl_free(name);
}
if (!radius_request(&reference, request_name)) {
- RDEBUG("WARNING: Attribute name refers to outer request"
+ RDEBUGW("Attribute name refers to outer request"
" but not in a tunnel, skipping");
curl_free(name);
list_name = radius_list_name(&attribute, PAIR_LIST_REPLY);
if (list_name == PAIR_LIST_UNKNOWN) {
- RDEBUG("WARNING: Invalid list qualifier, skipping");
+ RDEBUGW("Invalid list qualifier, skipping");
curl_free(name);
da = dict_attrbyname(attribute);
if (!da) {
- RDEBUG("WARNING: Attribute \"%s\" unknown, skipping",
+ RDEBUGW("Attribute \"%s\" unknown, skipping",
attribute);
curl_free(name);
RDEBUG2("\tLength : %i", curl_len);
RDEBUG2("\tValue : \"%s\"", value);
+
+ RDEBUG("Performing xlat expansion of response value");
+
+ if (!radius_xlat(buffer, sizeof(buffer),
+ value, request, NULL, NULL)) {
+ goto skip;
+ }
- vp = paircreate(da->attr, da->vendor, da->type);
+ vp = pairalloc(NULL, da);
if (!vp) {
radlog(L_ERR, "rlm_rest (%s): Failed creating"
- " value-pair", instance->xlat_name);
+ " valuepair", instance->xlat_name);
goto error;
}
*/
current = processed;
while (*current++) {
- if ((current[0]->attr == da->attr) &&
- (current[0]->vendor == da->vendor)) {
+ if (current[0] == da) {
vp->op = T_OP_ADD;
break;
}
current[1] = NULL;
}
- tmp = pairparsevalue(vp, value);
- if (tmp == NULL) {
+ if (!pairparsevalue(vp, buffer)) {
RDEBUG("Incompatible value assignment, skipping");
pairbasicfree(vp);
goto skip;
}
- vp = tmp;
-
- rest_check_truncation(request, value, vp);
-
- vp->flags.do_xlat = 1;
-
- RDEBUG("Performing xlat expansion of response value", value);
- pairxlatmove(request, vps, &vp);
if (++count == REST_BODY_MAX_ATTRS) {
radlog(L_ERR, "rlm_rest (%s): At maximum"
REQUEST *request, const DICT_ATTR *da,
json_flags_t *flags, json_object *leaf)
{
- const char *value;
- VALUE_PAIR *vp, *tmp;
+ const char *value, *to_parse;
+ char buffer[1024];
+
+ VALUE_PAIR *vp;
/*
* Should encode any nested JSON structures into JSON strings.
RDEBUG2("\tLength : %i", strlen(value));
RDEBUG2("\tValue : \"%s\"", value);
- vp = paircreate(da->attr, da->vendor, da->type);
+ if (flags->do_xlat) {
+ if (!radius_xlat(buffer, sizeof(buffer), value,
+ request, NULL, NULL)) {
+ return NULL;
+ }
+
+ to_parse = buffer;
+ } else {
+ to_parse = value;
+ }
+
+ vp = paircreate(da->attr, da->vendor);
if (!vp) {
- radlog(L_ERR, "rlm_rest (%s): Failed creating value-pair",
+ radlog(L_ERR, "rlm_rest (%s): Failed creating valuepair",
instance->xlat_name);
return NULL;
}
vp->op = flags->op;
-
- tmp = pairparsevalue(vp, value);
- if (tmp == NULL) {
+
+ if (!pairparsevalue(vp, to_parse)) {
RDEBUG("Incompatible value assignment, skipping");
pairbasicfree(vp);
return NULL;
}
- vp = tmp;
-
- rest_check_truncation(request, value, vp);
-
- if (flags->do_xlat) vp->flags.do_xlat = 1;
return vp;
}
json_flags_t flags;
const DICT_ATTR *da;
- VALUE_PAIR *vp;
+ VALUE_PAIR *vp = NULL;
request_refs_t request_name;
pair_lists_t list_name;
request_name = radius_request_name(&attribute, REQUEST_CURRENT);
if (request_name == REQUEST_UNKNOWN) {
- RDEBUG("WARNING: Request qualifier, skipping");
+ RDEBUGW("Request qualifier unknown, skipping");
continue;
}
if (!radius_request(&reference, request_name)) {
- RDEBUG("WARNING: Attribute name refers to outer request"
+ RDEBUGW("Attribute name refers to outer request"
" but not in a tunnel, skipping");
continue;
list_name = radius_list_name(&attribute, PAIR_LIST_REPLY);
if (list_name == PAIR_LIST_UNKNOWN) {
- RDEBUG("WARNING: Invalid list qualifier, skipping");
+ RDEBUGW("Invalid list qualifier, skipping");
continue;
}
da = dict_attrbyname(attribute);
if (!da) {
- RDEBUG("WARNING: Attribute \"%s\" unknown, skipping",
+ RDEBUGW("Attribute \"%s\" unknown, skipping",
attribute);
continue;
*/
tmp = json_object_object_get(value, "op");
if (tmp) {
- flags.op = fr_str2int(fr_tokens,
- json_object_get_string(tmp), 0);
-
+ flags.op = fr_str2int(fr_tokens, json_object_get_string(tmp), 0);
if (!flags.op) {
RDEBUG("Invalid operator value \"%s\","
" skipping", tmp);
}
}
- /*
- * Setup pairmake / recursion loop.
- */
- if (!flags.is_json &&
- json_object_is_type(value, json_type_array)) {
- len = json_object_array_length(value);
- if (!len) {
- RDEBUG("Zero length value array, skipping", value);
- continue;
- }
- idx = json_object_array_get_idx(value, 0);
- } else {
- len = 1;
- idx = value;
- }
-
- i = 0;
- do {
- if (!(*max_attrs)--) {
- radlog(L_ERR, "rlm_rest (%s): At maximum"
- " attribute limit", instance->xlat_name);
- return NULL;
- }
+ /*
+ * Setup pairmake / recursion loop.
+ */
+ if (!flags.is_json &&
+ json_object_is_type(value, json_type_array)) {
+ len = json_object_array_length(value);
+ if (!len) {
+ RDEBUG("Zero length value array, skipping",
+ value);
+ continue;
+ }
+ idx = json_object_array_get_idx(value, 0);
+ } else {
+ len = 1;
+ idx = value;
+ }
- /*
- * Automagically switch the op for multivalued
- * attributes.
- */
- if (((flags.op == T_OP_SET) ||
- (flags.op == T_OP_EQ)) && (len > 1)) {
- flags.op = T_OP_ADD;
- }
+ i = 0;
+ do {
+ if (!(*max_attrs)--) {
+ radlog(L_ERR, "rlm_rest (%s): At "
+ "maximum attribute limit",
+ instance->xlat_name);
+ return NULL;
+ }
- if (!flags.is_json &&
- json_object_is_type(value, json_type_object)) {
- /* TODO: Insert nested VP into VP structure...*/
- RDEBUG("Found nested VP", value);
- vp = json_pairmake(instance, section,
- request, value,
- level + 1, max_attrs);
- } else {
- vp = json_pairmake_leaf(instance, section,
- request, da, &flags,
- idx);
-
- if (vp != NULL) {
- if (vp->flags.do_xlat) {
- RDEBUG("Performing xlat"
- " expansion of response"
- " value", value);
- }
+ /*
+ * Automagically switch the op for multivalued
+ * attributes.
+ */
+ if (((flags.op == T_OP_SET) ||
+ (flags.op == T_OP_EQ)) && (len > 1)) {
+ flags.op = T_OP_ADD;
+ }
- pairxlatmove(request, vps, &vp);
+ if (!flags.is_json &&
+ json_object_is_type(value, json_type_object)) {
+ /* TODO: Insert nested VP into VP structure...*/
+ RDEBUG("Found nested VP", value);
+ vp = json_pairmake(instance, section,
+ request, value,
+ level + 1, max_attrs);
+ } else {
+ vp = json_pairmake_leaf(instance, section,
+ request, da, &flags,
+ idx);
}
- }
- } while ((++i < len) && (idx = json_object_array_get_idx(value, i)));
+ } while ((++i < len) &&
+ (idx = json_object_array_get_idx(value, i)));
}
return vp;
CURLOPT_CUSTOMREQUEST,
section->method);
if (ret != CURLE_OK) goto error;
+ break;
default:
assert(0);
return FALSE;
}
- RDEBUG("Processing body", ret);
+ RDEBUG("Processing body");
switch (ctx->write.type)
{