Initialize VP to NULL.
[freeradius.git] / src / modules / rlm_rest / rest.c
index e93a905..22ad177 100644 (file)
@@ -196,8 +196,8 @@ const FR_NAME_NUMBER http_content_type_table[] = {
  * @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
@@ -381,7 +381,7 @@ int rest_socket_alive(void *instance, void *handle)
        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"
@@ -478,11 +478,11 @@ static size_t rest_encode_post(void *ptr, size_t size, size_t nmemb,
                        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)) {
@@ -657,18 +657,18 @@ static size_t rest_encode_json(void *ptr, size_t size, size_t nmemb,
                 *      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;
 
@@ -703,9 +703,8 @@ static size_t rest_encode_json(void *ptr, size_t size, size_t nmemb,
                        /* 
                         *      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++;
 
@@ -894,14 +893,8 @@ static void rest_read_ctx_init(REQUEST *request,
        /* 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;
@@ -927,30 +920,6 @@ static void rest_read_ctx_free(rlm_rest_read_t *ctx)
        }
 }
 
-/** 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
@@ -985,12 +954,13 @@ static int rest_decode_post(rlm_rest_t *instance,
        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;
@@ -1022,7 +992,7 @@ static int rest_decode_post(rlm_rest_t *instance,
                
                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);
 
@@ -1030,7 +1000,7 @@ static int rest_decode_post(rlm_rest_t *instance,
                }
 
                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);
@@ -1040,7 +1010,7 @@ static int rest_decode_post(rlm_rest_t *instance,
 
                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);
 
@@ -1049,7 +1019,7 @@ static int rest_decode_post(rlm_rest_t *instance,
 
                da = dict_attrbyname(attribute);
                if (!da) {
-                       RDEBUG("WARNING: Attribute \"%s\" unknown, skipping",
+                       RDEBUGW("Attribute \"%s\" unknown, skipping",
                               attribute);
 
                        curl_free(name);
@@ -1078,11 +1048,18 @@ static int rest_decode_post(rlm_rest_t *instance,
 
                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;
                }
@@ -1096,8 +1073,7 @@ static int rest_decode_post(rlm_rest_t *instance,
                 */
                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;
                        }
@@ -1108,20 +1084,11 @@ static int rest_decode_post(rlm_rest_t *instance,
                        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"
@@ -1173,8 +1140,10 @@ static VALUE_PAIR *json_pairmake_leaf(rlm_rest_t *instance,
                                      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.
@@ -1188,26 +1157,31 @@ static VALUE_PAIR *json_pairmake_leaf(rlm_rest_t *instance,
        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;
 }
@@ -1277,7 +1251,7 @@ static VALUE_PAIR *json_pairmake(rlm_rest_t *instance,
        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;
@@ -1329,13 +1303,13 @@ static VALUE_PAIR *json_pairmake(rlm_rest_t *instance,
                
                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;
@@ -1343,14 +1317,14 @@ static VALUE_PAIR *json_pairmake(rlm_rest_t *instance,
 
                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;
@@ -1382,9 +1356,7 @@ static VALUE_PAIR *json_pairmake(rlm_rest_t *instance,
                         */
                        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);
@@ -1419,62 +1391,55 @@ static VALUE_PAIR *json_pairmake(rlm_rest_t *instance,
                        }
                }
 
-       /*
-        *      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;
@@ -2003,6 +1968,7 @@ int rest_request_config(rlm_rest_t *instance, rlm_rest_section_t *section,
                                               CURLOPT_CUSTOMREQUEST,
                                               section->method);
                        if (ret != CURLE_OK) goto error;
+                       break;
 
                default:
                        assert(0);
@@ -2273,7 +2239,7 @@ int rest_request_decode(rlm_rest_t *instance,
                return FALSE;
        }
 
-       RDEBUG("Processing body", ret);
+       RDEBUG("Processing body");
 
        switch (ctx->write.type)
        {