25RCSID(
"$Id: 55024c8503d4e06dcbe9209da6ae6e018ebc068f $")
27#define LOG_PREFIX mctx->mi->name
33#include <freeradius-devel/server/base.h>
34#include <freeradius-devel/unlang/call.h>
35#include <freeradius-devel/util/skip.h>
77#ifndef CURLOPT_TLSAUTH_SRP
78# define CURLOPT_TLSAUTH_SRP 0
81# define CURLAUTH_BASIC 0
83#ifndef CURLAUTH_DIGEST
84# define CURLAUTH_DIGEST 0
86#ifndef CURLAUTH_DIGEST_IE
87# define CURLAUTH_DIGEST_IE 0
89#ifndef CURLAUTH_GSSNEGOTIATE
90# define CURLAUTH_GSSNEGOTIATE 0
93# define CURLAUTH_NTLM 0
95#ifndef CURLAUTH_NTLM_WB
96# define CURLAUTH_NTLM_WB 0
244 curl_easy_cleanup(randle->
candle);
274 if (!randle)
return NULL;
282 randle->
uctx = curl_ctx;
303 size_t freespace = (size * nmemb) - 1;
310 if (
data->len == 0)
return 0;
319 len = to_copy > freespace ? freespace : to_copy;
320 if (len == 0)
return 0;
365 size_t freespace = (size * nmemb) - 1;
372 if ((ctx->
chunk) && (ctx->
chunk <= freespace)) freespace = (ctx->
chunk - 1);
379 while (freespace > 0) {
387 RDEBUG2(
"Encoding attribute \"%s\"",
vp->
da->name);
390 escaped = curl_escape(
vp->
da->name, 0);
392 REDEBUG(
"Failed escaping string \"%s\"",
vp->
da->name);
396 len = strlen(escaped);
397 if (freespace < (1 + len)) {
405 len = encoded - (
char *)
out;
413 REDEBUG(
"Failed encoding attribute");
415 RDEBUG3(
"Returning %zd bytes of POST data "
416 "(buffer full or chunk exceeded)", len);
422 len =
snprintf(p, freespace,
"%s=", escaped);
438 if (slen < 0)
return 0;
441 RDEBUG3(
"Length : %zd", (
size_t)slen);
444 escaped = curl_escape(p, (
size_t)slen);
446 REDEBUG(
"Failed escaping string \"%s\"",
vp->
da->name);
449 len = strlen(escaped);
451 if (freespace < len) {
456 len =
strlcpy(p, escaped, len + 1);
472 if (freespace < 1)
goto no_space;
487 len = p - (
char *)
out;
490 RDEBUG3(
"Returning %zd bytes of POST data", len);
540 size_t freespace = (size * nmemb) - 1;
549 if (!encoded)
return -1;
552 data->len = strlen(encoded);
554 RDEBUG3(
"JSON Data: %s", encoded);
555 RDEBUG3(
"Returning %zd bytes of JSON data",
data->len);
561 len = to_copy > freespace ? freespace : to_copy;
563 if (len == 0)
return 0;
605 buff = talloc_array(NULL,
char, needed);
615 if (needed > limit)
break;
617 MEM(
buff = talloc_realloc(NULL,
buff,
char, needed));
664 if (*raw ==
'\0')
return 0;
703 CURL *candle = randle->
candle;
705 char const *p = raw, *q;
714 if (*p ==
'\0')
return 0;
727 char *expanded = NULL;
734 name = curl_easy_unescape(candle, p, (q - p), &curl_len);
745 .dict_def = request->local_dict,
749 RPWDEBUG(
"Failed parsing attribute (skipping)");
755 RWDEBUG(
"Attribute name refers to outer request but not in a tunnel (skipping)");
762 RWDEBUG(
"List not valid in this context (skipping)");
775 len = (!q) ? (rawlen - (p - raw)) : (unsigned)(q - p);
777 value = curl_easy_unescape(candle, p, len, &curl_len);
784 p += (!q) ? len : (len + 1);
786 RDEBUG3(
"Length : %i", curl_len);
792 RDEBUG2(
"Performing xlat expansion of response value");
794 if (
xlat_aeval(request, &expanded, request,
value, NULL, NULL) < 0)
goto skip;
800 REDEBUG(
"Failed creating valuepair");
810 TALLOC_FREE(expanded);
812 RWDEBUG(
"Incompatible value assignment, skipping");
857 char *expanded = NULL;
864 if (json_object_is_type(leaf, json_type_null)) {
865 RDEBUG3(
"Got null value for attribute \"%s\" (skipping)", da->name);
871 RWDEBUG(
"Failed creating valuepair for attribute \"%s\" (skipping)", da->name);
877 switch (json_object_get_type(leaf)) {
879 if (flags->
do_xlat)
RWDEBUG(
"Ignoring do_xlat on 'int', attribute \"%s\"", da->name);
880 fr_value_box(&src, (int32_t)json_object_get_int(leaf),
true);
883 case json_type_double:
884 if (flags->
do_xlat)
RWDEBUG(
"Ignoring do_xlat on 'double', attribute \"%s\"", da->name);
885 fr_value_box(&src, (
double)json_object_get_double(leaf),
true);
888 case json_type_string:
889 value = json_object_get_string(leaf);
890 if (flags->
do_xlat && memchr(
value,
'%', json_object_get_string_len(leaf))) {
899 json_object_get_string_len(leaf),
true);
906 if (flags->
do_xlat)
RWDEBUG(
"Ignoring do_xlat on 'object', attribute \"%s\"", da->name);
913 str = json_object_get_string(leaf);
915 RWDEBUG(
"Failed getting string value for attribute \"%s\" (skipping)", da->name);
926 RWDEBUG(
"Failed parsing value for attribute \"%s\" (skipping)", da->name);
994 if (!json_object_is_type(
object, json_type_object)) {
995#ifdef HAVE_JSON_TYPE_TO_NAME
996 REDEBUG(
"Can't process VP container, expected JSON object"
997 "got \"%s\" (skipping)",
998 json_type_to_name(json_object_get_type(
object)));
1000 REDEBUG(
"Can't process VP container, expected JSON object"
1010 json_object_object_foreach(
object,
name,
value) {
1011 int i = 0, elements;
1012 struct json_object *element, *tmp;
1035 .dict_def = request->local_dict,
1039 RPWDEBUG(
"Failed parsing attribute (skipping)");
1044 RWDEBUG(
"Attribute name refers to outer request but not in a tunnel (skipping)");
1050 RWDEBUG(
"List not valid in this context (skipping)");
1071 if (json_object_is_type(
value, json_type_object)) {
1075 if (json_object_object_get_ex(
value,
"op", &tmp)) {
1078 RWDEBUG(
"Invalid operator value \"%s\" (skipping)",
1079 json_object_get_string(tmp));
1087 if (json_object_object_get_ex(
value,
"do_xlat", &tmp)) {
1088 flags.
do_xlat = json_object_get_boolean(tmp);
1094 if (json_object_object_get_ex(
value,
"is_json", &tmp)) {
1095 flags.
is_json = json_object_get_boolean(tmp);
1101 if (!json_object_object_get_ex(
value,
"value", &tmp)) {
1102 RWDEBUG(
"Value key missing (skipping)");
1115 if (!flags.
is_json && json_object_is_type(
value, json_type_array)) {
1116 elements = json_object_array_length(
value);
1118 RWDEBUG(
"Zero length value array (skipping)");
1121 element = json_object_array_get_idx(
value, 0);
1134 if (max_attrs-- <= 0) {
1135 RWDEBUG(
"At maximum attribute limit");
1147 if (json_object_is_type(element, json_type_object) && !flags.
is_json) {
1149 RWDEBUG(
"Found nested VP, these are not yet supported (skipping)");
1173 }
while ((++i < elements) && (element = json_object_array_get_idx(
value, i)));
1179 return max - max_attrs;
1205 char const *p = raw;
1207 struct json_object *json;
1215 if (*p ==
'\0')
return 0;
1217 json = json_tokener_parse(p);
1219 REDEBUG(
"Malformed JSON data \"%s\"", raw);
1228 json_object_put(json);
1255 char const *start = (
char *)
in, *p = start, *end = p + (size * nmemb);
1263 REDEBUG(
"Forcing header decode failure");
1271 if (((end - p) == 2) && ((p[0] ==
'\r') && (p[1] ==
'\n'))) {
1277 if (ctx->
code == 100) {
1282 return (end - start);
1285 switch (ctx->
state) {
1287 RDEBUG2(
"Processing response header");
1295 if ((end - p) < 12) {
1296 REDEBUG(
"Malformed HTTP header: Status line too short");
1298 REDEBUG(
"Received %zu bytes of invalid header data: %pV",
1308 return (end - start);
1314 REDEBUG(
"Malformed HTTP header: Missing HTTP version");
1322 q = memchr(p,
' ', (end - p));
1324 REDEBUG(
"Malformed HTTP header: Missing reason code");
1335 if ((end - p) < 6) {
1336 REDEBUG(
"Malformed HTTP header: Reason code too short");
1344 if (!isdigit(p[0]) || !isdigit(p[1]) || !isdigit(p[2]) || !((p[3] ==
' ') || (p[3] ==
'\r'))) {
1345 REDEBUG(
"Malformed HTTP header: Reason code malformed. "
1346 "Expected three digits then space or end of header, got \"%pV\"",
1355 ctx->
code = (int)strtoul(p, &q, 10);
1365 q = memchr(p,
'\r', (end - p));
1366 if (!q)
goto malformed;
1378 if (((end - p) >= 14) &&
1385 q = memchr(p,
';', (end - p));
1390 if (!q) q = memchr(p,
'\r', (end - p));
1392 len = (
size_t)(!q ? (end - p) : (q - p));
1405 RDEBUG3(
"Forcing body type to \"%s\"",
1423 switch (ctx->
type) {
1425 RWDEBUG(
"Couldn't determine type, using the request's type \"%s\".",
1430 REDEBUG(
"Type \"%s\" is currently unsupported",
1435 REDEBUG(
"Type \"%s\" is unavailable, please rebuild this module with the required "
1440 REDEBUG(
"Type \"%s\" is not a valid web API data markup format",
1456 return (end - start);
1477 char const *start =
in, *p = start, *end = p + (size * nmemb);
1482 if (start == end)
return 0;
1486 REDEBUG(
"Forcing body read failure");
1496 switch (ctx->
type) {
1502 while ((q = memchr(p,
'\n', (end - p)))) {
1511 while ((q = memchr(p,
'\n', (end - p)))) {
1524 REDEBUG(
"Incoming data (%zu bytes) exceeds max_body_in (%zu bytes). "
1527 TALLOC_FREE(ctx->
buffer);
1532 if (needed > ctx->
alloc) {
1534 ctx->
alloc = needed;
1538 memcpy(out_p, p, (end - p));
1541 ctx->
used += (end - p);
1546 return (end - start);
1556 char const *p, *end;
1561 if (len == 0)
return;
1565 RERROR(
"Server returned:");
1566 while ((q = memchr(p,
'\n', (end - p)))) {
1581 char const *p, *end;
1586 if (len == 0)
return;
1591 while ((q = memchr(p,
'\n', (end - p)))) {
1625 TALLOC_FREE(ctx->
buffer);
1708 REDEBUG(
"Failed creating HTTP body content");
1711 RDEBUG2(
"Content-Length will be %zu bytes", len);
1713 fr_assert((len == 0) || (talloc_array_length(uctx->
body) >= (
size_t)len));
1736 struct curl_slist *headers;
1738 if (validate && !strchr(header,
':')) {
1739 RWDEBUG(
"Invalid HTTP header \"%s\" must be in format '<attribute>: <value>'. Skipping...",
1748 headers = curl_slist_append(ctx->
headers, header);
1750 REDEBUG(
"Failed to add header \"%s\"", header);
1771 struct curl_slist *headers = ctx->
headers;
1775 sep = strchr(header,
':');
1776 cmp_len = sep ? (
size_t)(sep - header) : strlen(header);
1779 if (
strncasecmp(headers->data, header, cmp_len) == 0)
return true;
1780 headers = headers->next;
1816 char const *uri,
char const *body_data)
1821 CURL *candle = randle->
candle;
1826 CURLcode ret = CURLE_OK;
1844#if CURL_AT_LEAST_VERSION(7,85,0)
1859 timeout =
inst->conn_config.connect_timeout;
1860 RDEBUG3(
"Connect timeout is %pVs, request timeout is %pVs",
1868 RDEBUG3(
"Adding custom headers:");
1878 if (call_env->
request.header) {
1879 size_t len = talloc_array_length(call_env->
request.header), i;
1880 for (i = 0; i < len; i++) {
1915 RDEBUG3(
"Request body content-type will be \"%s\"", content_type);
1966#define SET_AUTH_OPTION(_x, _y)\
1968 if ((ret = curl_easy_setopt(candle, _x, _y)) != CURLE_OK) {\
1969 option = STRINGIFY(_x);\
1970 REDEBUG("Failed setting curl option %s: %s (%i)", option, curl_easy_strerror(ret), ret); \
1974 RDEBUG3(
"Configuring HTTP auth type %s, user \"%pV\", password \"%pV\"",
2016 RDEBUG3(
"Using a HTTP method which does not require a body. Forcing request body type to \"none\"");
2121 RDEBUG2(
"Skipping attribute processing, no valid body data received");
2170 escaped = curl_escape(raw, 0);
2195 CURL *candle = randle->
candle;
2209 if (!p || (*++p !=
'/') || (*++p !=
'/')) {
2211 REDEBUG(
"URI \"%s\" is malformed, can't find start of path", uri);
2214 p = strchr(p + 1,
'/');
2224 scheme = curl_easy_unescape(candle, uri, len, NULL);
2226 REDEBUG(
"Error unescaping host");
static int const char char buffer[256]
#define L(_str)
Helper for initialising arrays of string literals.
CONF_SECTION * unlang_call_current(request_t *request)
Return the last virtual server that was called.
char const * cf_section_name2(CONF_SECTION const *cs)
Return the second identifier of a CONF_SECTION.
#define FR_CURL_REQUEST_SET_OPTION(_x, _y)
fr_curl_io_request_t * fr_curl_io_request_alloc(TALLOC_CTX *ctx)
Allocate a new curl easy request and wrapper struct.
void * uctx
Private data for the module using the API.
CURL * candle
Request specific handle.
Structure representing an individual request being passed to curl for processing.
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
static void * fr_dcursor_remove(fr_dcursor_t *cursor)
Remove the current item.
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
#define RADIUSD_VERSION_STRING
char * fr_json_afrom_pair_list(TALLOC_CTX *ctx, fr_pair_list_t *vps, fr_json_format_t const *format)
Returns a JSON string of a list of value pairs.
int fr_curl_easy_tls_init(fr_curl_io_request_t *randle, fr_curl_tls_t const *conf)
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RPWDEBUG(fmt,...)
#define RINDENT()
Indent R* messages by one level.
#define ROUND_UP(_num, _mul)
Round up - Works in all cases, but is slower.
int strncasecmp(char *s1, char *s2, int n)
void * env_data
Per call environment data.
module_instance_t const * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, UNUSED bool tainted)
Convert string value to native attribute value.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
fr_pair_t * fr_pair_afrom_da(TALLOC_CTX *ctx, fr_dict_attr_t const *da)
Dynamically allocate a new attribute and assign a fr_dict_attr_t.
void fr_pair_list_init(fr_pair_list_t *list)
Initialise a pair list header.
int fr_pair_value_bstrndup(fr_pair_t *vp, char const *src, size_t len, bool tainted)
Copy data into a "string" type value pair.
void radius_pairmove(request_t *request, fr_pair_list_t *to, fr_pair_list_t *from)
#define pair_update_request(_attr, _da)
fr_dict_attr_t const * request_attr_reply
static int rest_decode_post(UNUSED rlm_rest_t const *instance, UNUSED rlm_rest_section_t const *section, request_t *request, fr_curl_io_request_t *randle, char *raw, size_t rawlen)
Converts POST response into fr_pair_ts and adds them to the request.
static int rest_decode_plain(UNUSED rlm_rest_t const *inst, UNUSED rlm_rest_section_t const *section, request_t *request, UNUSED fr_curl_io_request_t *randle, char *raw, size_t rawlen)
Converts plain response into a single fr_pair_t.
fr_table_num_sorted_t const http_auth_table[]
size_t len
Length of data.
char const * start
Start of the buffer.
#define CURLAUTH_DIGEST_IE
int rest_request_config(module_ctx_t const *mctx, rlm_rest_section_t const *section, request_t *request, fr_curl_io_request_t *randle, http_method_t method, http_body_type_t type, char const *uri, char const *body_data)
Configures request curlopts.
ssize_t rest_uri_host_unescape(char **out, UNUSED rlm_rest_t const *inst, request_t *request, fr_curl_io_request_t *randle, char const *uri)
Unescapes the host portion of a URI string.
http_body_type_t rest_response_body_type_get(fr_curl_io_request_t *randle)
Return the body type of a HTTP response.
int do_xlat
If true value will be expanded with xlat.
static size_t rest_encode_custom(void *out, size_t size, size_t nmemb, void *userdata)
Copies a pre-expanded xlat string to the output buffer.
fr_table_num_sorted_t const http_body_type_table[]
Conversion table for type config values.
static size_t rest_encode_json(void *out, size_t size, size_t nmemb, void *userdata)
Encodes fr_pair_t linked list in JSON format.
#define CURLOPT_TLSAUTH_SRP
fr_token_t op
The operator that determines how the new VP.
fr_table_num_sorted_t const http_method_table[]
Conversion table for method config values.
void * rest_mod_conn_create(TALLOC_CTX *ctx, void *instance, UNUSED fr_time_delta_t timeout)
Creates a new connection handle for use by the FR connection API.
size_t rest_get_handle_data(char const **out, fr_curl_io_request_t *randle)
Extracts pointer to buffer containing response data.
static bool rest_request_contains_header(fr_curl_io_request_t *randle, char const *header)
See if the list of headers already contains a header.
static int json_pair_alloc(rlm_rest_t const *instance, rlm_rest_section_t const *section, request_t *request, json_object *object, UNUSED int level, int max)
Processes JSON response and converts it into multiple fr_pair_ts.
static void rest_request_init(rlm_rest_section_t const *section, request_t *request, rlm_rest_request_t *ctx)
(Re-)Initialises the data in a rlm_rest_request_t.
static ssize_t rest_request_encode_wrapper(char **out, UNUSED rlm_rest_t const *inst, rest_read_t func, size_t limit, void *userdata)
Emulates successive libcurl calls to an encoding function.
static int rest_decode_json(rlm_rest_t const *instance, rlm_rest_section_t const *section, request_t *request, UNUSED fr_curl_io_request_t *randle, char *raw, UNUSED size_t rawlen)
Converts JSON response into fr_pair_ts and adds them to the request.
void rest_response_debug(request_t *request, fr_curl_io_request_t *handle)
Print out the response text.
static fr_pair_t * json_pair_alloc_leaf(UNUSED rlm_rest_t const *instance, UNUSED rlm_rest_section_t const *section, TALLOC_CTX *ctx, request_t *request, fr_dict_attr_t const *da, json_flags_t *flags, json_object *leaf)
Converts JSON "value" key into fr_pair_t.
fr_table_num_sorted_t const http_content_type_table[]
Conversion table for "Content-Type" header values.
#define SET_AUTH_OPTION(_x, _y)
int is_json
If true value will be inserted as raw JSON.
const unsigned long http_curl_auth[REST_HTTP_AUTH_NUM_ENTRIES]
const http_body_type_t http_body_type_supported[REST_HTTP_BODY_NUM_ENTRIES]
Table of encoder/decoder support.
#define CURLAUTH_GSSNEGOTIATE
size_t rest_uri_escape(UNUSED request_t *request, char *out, size_t outlen, char const *raw, UNUSED void *arg)
URL encodes a string.
int rest_request_config_add_header(request_t *request, fr_curl_io_request_t *randle, char const *header, bool validate)
Adds an additional header to a handle to use in the next reques.
void rest_response_error(request_t *request, fr_curl_io_request_t *handle)
Print out the response text as error lines.
size_t http_body_type_table_len
static int rest_request_config_body(module_ctx_t const *mctx, rlm_rest_section_t const *section, request_t *request, fr_curl_io_request_t *randle, rest_read_t func)
Configures body specific curlopts.
static int _mod_conn_free(fr_curl_io_request_t *randle)
Frees a libcurl handle, and any additional memory used by context data.
static void rest_response_init(rlm_rest_section_t const *section, request_t *request, rlm_rest_response_t *ctx, http_body_type_t type, tmpl_t *header)
(Re-)Initialises the data in a rlm_rest_response_t.
static size_t rest_response_body(void *in, size_t size, size_t nmemb, void *userdata)
Processes incoming HTTP body data from libcurl.
static size_t rest_encode_post(void *out, size_t size, size_t nmemb, void *userdata)
Encodes fr_pair_t linked list in POST format.
char const * p
how much text we've sent so far.
size_t http_auth_table_len
static size_t rest_response_header(void *in, size_t size, size_t nmemb, void *userdata)
Processes incoming HTTP header data from libcurl.
size_t http_content_type_table_len
const bool http_body_type_binary[REST_HTTP_BODY_NUM_ENTRIES]
Table of which known body types are expected to give binary data.
size_t http_method_table_len
int rest_response_decode(rlm_rest_t const *instance, rlm_rest_section_t const *section, request_t *request, fr_curl_io_request_t *randle)
Sends the response to the correct decode function.
Flags to control the conversion of JSON values to fr_pair_ts.
Function prototypes and datatypes for the REST (HTTP) transport.
rlm_rest_t const * instance
This instance of rlm_rest.
read_state_t state
Encoder state.
HIDDEN fr_dict_attr_t const * attr_rest_http_header
http_auth_type_t auth
HTTP auth type.
struct curl_slist * headers
Any HTTP headers which will be sent with the request.
tmpl_t * header
Where to create pairs representing HTTP response headers.
request_t * request
Current request.
char * buffer
Raw incoming HTTP data.
int code
HTTP Status Code.
write_state_t state
Decoder state.
bool fail_header_decode
Force header decoding to fail for debugging purposes.
char const * proxy
Send request via this proxy.
size_t used
Space used in buffer.
http_body_type_t type
HTTP Content Type.
char * body
Pointer to the buffer which contains body data/ Only used when not performing chunked encoding.
#define REST_BODY_MAX_ATTRS
bool fail_body_decode
Force body decoding to fail for debugging purposes.
http_body_type_t force_to
Override the Content-Type header in the response to force decoding as a particular type.
@ REST_HTTP_METHOD_DELETE
@ REST_HTTP_METHOD_UNKNOWN
@ REST_HTTP_METHOD_CUSTOM
Must always come last, should not be in method table.
size_t max_body_in
Maximum size of incoming data.
fr_dcursor_t cursor
Cursor pointing to the start of the list to encode.
http_body_type_t force_to
Force decoding the body type as a particular encoding.
@ REST_HTTP_BODY_UNSUPPORTED
@ REST_HTTP_BODY_NUM_ENTRIES
@ REST_HTTP_BODY_UNAVAILABLE
char const * method_str
The string version of the HTTP method.
rlm_rest_section_t const * section
Section configuration.
char const * body_str
The string version of the encoding/content type.
#define REST_BODY_ALLOC_CHUNK
HIDDEN fr_dict_attr_t const * attr_rest_http_body
rlm_rest_section_request_t request
Request configuration.
struct rlm_rest_call_env_t::@190 response
rlm_rest_response_t response
Response context data.
size_t(* rest_read_t)(void *ptr, size_t size, size_t nmemb, void *userdata)
#define REST_BODY_MAX_LEN
rlm_rest_section_t const * section
Section configuration.
struct rlm_rest_call_env_t::@189 request
void * encoder
Encoder specific data.
bool accept_all
Accept all content types.
rlm_rest_request_t request
Request context data.
rlm_rest_section_response_t response
Response configuration.
fr_time_delta_t timeout
Timeout timeval.
@ WRITE_STATE_PARSE_HEADERS
@ WRITE_STATE_PARSE_CONTENT
char const * name
Section name.
@ REST_HTTP_AUTH_NUM_ENTRIES
@ REST_HTTP_AUTH_GSSNEGOTIATE
@ REST_HTTP_AUTH_DIGEST_IE
@ REST_HTTP_AUTH_ANY_SAFE
size_t alloc
Space allocated for buffer.
request_t * request
Current request.
rlm_rest_t const * instance
This instance of rlm_rest.
char const * rest_no_proxy
Magic pointer value for determining if we should disable proxying.
uint32_t chunk
Max chunk-size (mainly for testing the encoders)
#define FR_SBUFF_OUT(_start, _len_or_end)
void * data
Module's instance data.
static fr_dict_attr_t const * tmpl_list(tmpl_t const *vpt)
ssize_t tmpl_afrom_attr_str(TALLOC_CTX *ctx, tmpl_attr_error_t *err, tmpl_t **out, char const *name, tmpl_rules_t const *rules))
Parse a string into a TMPL_TYPE_ATTR_* type tmpl_t.
fr_pair_list_t * tmpl_list_head(request_t *request, fr_dict_attr_t const *list)
Resolve attribute fr_pair_list_t value to an attribute list.
TALLOC_CTX * tmpl_list_ctx(request_t *request, fr_dict_attr_t const *list)
Return the correct TALLOC_CTX to alloc fr_pair_t in, for a list.
int tmpl_request_ptr(request_t **request, FR_DLIST_HEAD(tmpl_request_list) const *rql)
Resolve a tmpl_request_ref_t to a request_t.
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
static char const * tmpl_list_name(fr_dict_attr_t const *list, char const *def)
Return the name of a tmpl list or def if list not provided.
Optional arguments passed to vp_tmpl functions.
static char buff[sizeof("18446744073709551615")+3]
#define fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
eap_aka_sim_process_conf_t * inst
fr_aka_sim_id_type_t type
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 fr_table_value_by_str(_table, _name, _def)
Convert a string to a value using a sorted or ordered table.
#define fr_table_str_by_value(_table, _number, _def)
Convert an integer to a string.
#define fr_table_value_by_substr(_table, _name, _name_len, _def)
Convert a partial string to a value using an ordered or sorted table.
An element in a lexicographically sorted array of name to num mappings.
char * talloc_bstr_realloc(TALLOC_CTX *ctx, char *in, size_t inlen)
Trim a bstr (char) buffer.
char * talloc_typed_asprintf(TALLOC_CTX *ctx, char const *fmt,...)
Call talloc vasprintf, setting the type on the new chunk correctly.
#define talloc_get_type_abort_const
static size_t talloc_strlen(char const *s)
Returns the length of a talloc array containing a string.
static int64_t fr_time_delta_to_msec(fr_time_delta_t delta)
A time delta, a difference in time measured in nanoseconds.
fr_table_num_ordered_t const fr_tokens_table[]
ssize_t xlat_aeval(TALLOC_CTX *ctx, char **out, request_t *request, char const *fmt, xlat_escape_legacy_t escape, void const *escape_ctx))
#define fr_pair_dcursor_by_da_init(_cursor, _list, _da)
Initialise a cursor that will return only attributes matching the specified fr_dict_attr_t.
ssize_t fr_pair_print_value_quoted(fr_sbuff_t *out, fr_pair_t const *vp, fr_token_t quote)
Print the value of an attribute to a string.
#define fr_pair_dcursor_init(_cursor, _list)
Initialises a special dcursor with callbacks that will maintain the attr sublists correctly.
static char const * fr_type_to_str(fr_type_t type)
Return a static string containing the type name.
int fr_value_box_cast(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_type_t dst_type, fr_dict_attr_t const *dst_enumv, fr_value_box_t const *src)
Convert one type of fr_value_box_t to another.
void fr_value_box_strdup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Assign a buffer containing a nul terminated string to a box, but don't copy it.
void fr_value_box_bstrndup_shallow(fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Assign a string to to a fr_value_box_t.
#define FR_VALUE_BOX_INITIALISER_NULL(_vb)
A static initialiser for stack/globally allocated boxes.
#define fr_box_strvalue_len(_val, _len)
#define fr_value_box_init_null(_vb)
Initialise an empty/null box that will be filled later.
#define fr_box_strvalue(_val)
#define fr_box_time_delta(_val)
#define fr_value_box(_box, _var, _tainted)
Automagically fill in a box, determining the value type from the type of the C variable.
#define fr_value_box_list_foreach(_list_head, _iter)
static size_t char ** out