25 RCSID(
"$Id: 6c0e2a62d2c78ba4fec1de10c285283e2c0f6b49 $")
27 #define LOG_PREFIX mctx->inst->name
33 #include <freeradius-devel/server/base.h>
34 #include <freeradius-devel/server/log.h>
35 #include <freeradius-devel/server/pool.h>
36 #include <freeradius-devel/server/tmpl.h>
37 #include <freeradius-devel/unlang/call.h>
38 #include <freeradius-devel/util/value.h>
73 #ifndef CURLOPT_TLSAUTH_SRP
74 # define CURLOPT_TLSAUTH_SRP 0
76 #ifndef CURLAUTH_BASIC
77 # define CURLAUTH_BASIC 0
79 #ifndef CURLAUTH_DIGEST
80 # define CURLAUTH_DIGEST 0
82 #ifndef CURLAUTH_DIGEST_IE
83 # define CURLAUTH_DIGEST_IE 0
85 #ifndef CURLAUTH_GSSNEGOTIATE
86 # define CURLAUTH_GSSNEGOTIATE 0
89 # define CURLAUTH_NTLM 0
91 #ifndef CURLAUTH_NTLM_WB
92 # define CURLAUTH_NTLM_WB 0
237 curl_easy_cleanup(randle->
candle);
272 if (!randle)
return NULL;
280 randle->
uctx = curl_ctx;
301 size_t freespace = (size * nmemb) - 1;
308 if (
data->len == 0)
return 0;
317 len = to_copy > freespace ? freespace : to_copy;
318 if (len == 0)
return 0;
363 size_t freespace = (size * nmemb) - 1;
370 if ((ctx->
chunk) && (ctx->
chunk <= freespace)) freespace = (ctx->
chunk - 1);
377 while (freespace > 0) {
385 RDEBUG2(
"Encoding attribute \"%s\"",
vp->
da->name);
388 escaped = curl_escape(
vp->
da->name, 0);
390 REDEBUG(
"Failed escaping string \"%s\"",
vp->
da->name);
394 len = strlen(escaped);
395 if (freespace < (1 + len)) {
403 len = encoded - (
char *)
out;
411 REDEBUG(
"Failed encoding attribute");
413 RDEBUG3(
"Returning %zd bytes of POST data "
414 "(buffer full or chunk exceeded)", len);
420 len =
snprintf(p, freespace,
"%s=", escaped);
436 if (slen < 0)
return 0;
439 RDEBUG3(
"Length : %zd", (
size_t)slen);
442 escaped = curl_escape(p, (
size_t)slen);
444 REDEBUG(
"Failed escaping string \"%s\"",
vp->
da->name);
447 len = strlen(escaped);
449 if (freespace < len) {
454 len =
strlcpy(p, escaped, len + 1);
470 if (freespace < 1)
goto no_space;
485 len = p - (
char *)
out;
488 RDEBUG3(
"Returning %zd bytes of POST data", len);
538 size_t freespace = (size * nmemb) - 1;
547 if (!encoded)
return -1;
550 data->len = strlen(encoded);
552 RDEBUG3(
"JSON Data: %s", encoded);
553 RDEBUG3(
"Returning %zd bytes of JSON data",
data->len);
559 len = to_copy > freespace ? freespace : to_copy;
561 if (len == 0)
return 0;
603 buff = talloc_array(NULL,
char, alloc);
613 if (alloc > limit)
break;
615 MEM(
buff = talloc_realloc(NULL,
buff,
char, alloc));
662 if (*raw ==
'\0')
return 0;
701 CURL *candle = randle->
candle;
703 char const *p = raw, *q;
712 if (*p ==
'\0')
return 0;
725 char *expanded = NULL;
732 name = curl_easy_unescape(candle, p, (q - p), &curl_len);
744 .dict_def = request->dict,
748 RPWDEBUG(
"Failed parsing attribute (skipping)");
754 RWDEBUG(
"Attribute name refers to outer request but not in a tunnel (skipping)");
761 RWDEBUG(
"List not valid in this context (skipping)");
774 len = (!q) ? (rawlen - (p - raw)) : (
unsigned)(q - p);
776 value = curl_easy_unescape(candle, p, len, &curl_len);
783 p += (!q) ? len : (len + 1);
785 RDEBUG3(
"Length : %i", curl_len);
791 RDEBUG2(
"Performing xlat expansion of response value");
793 if (
xlat_aeval(request, &expanded, request,
value, NULL, NULL) < 0)
goto skip;
799 REDEBUG(
"Failed creating valuepair");
809 TALLOC_FREE(expanded);
811 RWDEBUG(
"Incompatible value assignment, skipping");
856 char *expanded = NULL;
863 if (json_object_is_type(leaf, json_type_null)) {
864 RDEBUG3(
"Got null value for attribute \"%s\" (skipping)", da->name);
870 RWDEBUG(
"Failed creating valuepair for attribute \"%s\" (skipping)", da->name);
876 switch (json_object_get_type(leaf)) {
878 if (flags->
do_xlat)
RWDEBUG(
"Ignoring do_xlat on 'int', attribute \"%s\"", da->name);
879 fr_value_box(&src, (int32_t)json_object_get_int(leaf),
true);
882 case json_type_double:
883 if (flags->
do_xlat)
RWDEBUG(
"Ignoring do_xlat on 'double', attribute \"%s\"", da->name);
884 fr_value_box(&src, (
double)json_object_get_double(leaf),
true);
887 case json_type_string:
888 value = json_object_get_string(leaf);
889 if (flags->
do_xlat && memchr(
value,
'%', json_object_get_string_len(leaf))) {
895 talloc_array_length(expanded) - 1,
true);
898 json_object_get_string_len(leaf),
true);
905 if (flags->
do_xlat)
RWDEBUG(
"Ignoring do_xlat on 'object', attribute \"%s\"", da->name);
912 str = json_object_get_string(leaf);
914 RWDEBUG(
"Failed getting string value for attribute \"%s\" (skipping)", da->name);
925 RWDEBUG(
"Failed parsing value for attribute \"%s\" (skipping)", da->name);
993 if (!json_object_is_type(
object, json_type_object)) {
994 #ifdef HAVE_JSON_TYPE_TO_NAME
995 REDEBUG(
"Can't process VP container, expected JSON object"
996 "got \"%s\" (skipping)",
997 json_type_to_name(json_object_get_type(
object)));
999 REDEBUG(
"Can't process VP container, expected JSON object"
1009 json_object_object_foreach(
object,
name,
value) {
1010 int i = 0, elements;
1011 struct json_object *element, *tmp;
1035 .dict_def = request->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\"",
1414 switch (ctx->
type) {
1416 RWDEBUG(
"Couldn't determine type, using the request's type \"%s\".",
1421 REDEBUG(
"Type \"%s\" is currently unsupported",
1426 REDEBUG(
"Type \"%s\" is unavailable, please rebuild this module with the required "
1431 REDEBUG(
"Type \"%s\" is not a valid web API data markup format",
1447 return (end - start);
1468 char const *start =
in, *p = start, *end = p + (size * nmemb);
1473 if (start == end)
return 0;
1477 REDEBUG(
"Forcing body read failure");
1487 switch (ctx->
type) {
1491 while ((q = memchr(p,
'\n', (end - p)))) {
1500 while ((q = memchr(p,
'\n', (end - p)))) {
1513 REDEBUG(
"Incoming data (%zu bytes) exceeds max_body_in (%zu bytes). "
1516 TALLOC_FREE(ctx->
buffer);
1521 if (needed > ctx->
alloc) {
1523 ctx->
alloc = needed;
1527 memcpy(out_p, p, (end - p));
1530 ctx->
used += (end - p);
1535 return (end - start);
1545 char const *p, *end;
1550 if (len == 0)
return;
1554 RERROR(
"Server returned:");
1555 while ((q = memchr(p,
'\n', (end - p)))) {
1570 char const *p, *end;
1575 if (len == 0)
return;
1580 while ((q = memchr(p,
'\n', (end - p)))) {
1614 TALLOC_FREE(ctx->
buffer);
1684 REDEBUG(
"Failed creating HTTP body content");
1687 RDEBUG2(
"Content-Length will be %zu bytes", len);
1689 fr_assert((len == 0) || (talloc_array_length(uctx->
body) >= (
size_t)len));
1729 char const *uri,
char const *body_data)
1734 CURL *candle = randle->
candle;
1739 CURLcode ret = CURLE_OK;
1743 bool content_type_set =
false;
1758 #if CURL_AT_LEAST_VERSION(7,85,0)
1774 RDEBUG3(
"Connect timeout is %pVs, request timeout is %pVs",
1782 RDEBUG3(
"Adding custom headers:");
1789 if (!ctx->
headers)
goto error_header;
1796 if (!ctx->
headers)
goto error_header;
1801 if (call_env->
request.header) {
1802 size_t len = talloc_array_length(call_env->
request.header), i;
1803 for (i = 0; i < len; i++) {
1809 ctx->
headers = curl_slist_append(ctx->
headers, header->vb_strvalue);
1825 if (!strchr(header->vp_strvalue,
':')) {
1826 RWDEBUG(
"Invalid HTTP header \"%s\" must be in format '<attribute>: <value>'. Skipping...",
1827 header->vp_strvalue);
1832 RDEBUG3(
"%pV", &header->data);
1835 ctx->
headers = curl_slist_append(ctx->
headers, header->vp_strvalue);
1840 if (!content_type_set && (
strncasecmp(header->vp_strvalue,
"content-type:",
sizeof(
"content-type:") - 1) == 0)) {
1841 char const *content_type = header->vp_strvalue + (
sizeof(
"content-type:") - 1);
1843 while (isspace((
uint8_t)*content_type)) content_type++;
1845 RDEBUG3(
"Request body content-type provided as \"%s\"", content_type);
1847 content_type_set =
true;
1854 if (!content_type_set) {
1866 REDEBUG(
"Failed creating header");
1870 RDEBUG3(
"Request body content-type will be \"%s\"", content_type);
1921 #define SET_AUTH_OPTION(_x, _y)\
1923 if ((ret = curl_easy_setopt(candle, _x, _y)) != CURLE_OK) {\
1924 option = STRINGIFY(_x);\
1925 REDEBUG("Failed setting curl option %s: %s (%i)", option, curl_easy_strerror(ret), ret); \
1929 RDEBUG3(
"Configuring HTTP auth type %s, user \"%pV\", password \"%pV\"",
1971 RDEBUG3(
"Using a HTTP method which does not require a body. Forcing request body type to \"none\"");
1982 if (!ctx->
headers)
goto error_header;
1984 ctx->
headers = curl_slist_append(ctx->
headers,
"Transfer-Encoding: chunked");
1985 if (!ctx->
headers)
goto error_header;
2080 RDEBUG2(
"Skipping attribute processing, no valid body data received");
2129 escaped = curl_escape(raw, 0);
2154 CURL *candle = randle->
candle;
2168 if (!p || (*++p !=
'/') || (*++p !=
'/')) {
2170 REDEBUG(
"URI \"%s\" is malformed, can't find start of path", uri);
2173 p = strchr(p + 1,
'/');
2183 scheme = curl_easy_unescape(candle, uri, len, NULL);
2185 REDEBUG(
"Error unescaping host");
2200 return talloc_array_length(*
out) - 1;
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_remove(fr_dcursor_t *cursor)
Remove the current item.
static void * fr_dcursor_next(fr_dcursor_t *cursor)
Advanced the cursor to the next item.
static void * fr_dcursor_current(fr_dcursor_t *cursor)
Return the item the cursor current points to.
#define RADIUSD_VERSION_STRING
static fr_time_delta_t timeout
void *_CONST data
Module instance's parsed configuration.
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.
@ TMPL_ATTR_REF_PREFIX_NO
Attribute refs have no '&' prefix.
#define fr_skip_whitespace(_p)
Skip whitespace ('\t', '\n', '\v', '\f', '\r', ' ')
int strncasecmp(char *s1, char *s2, int n)
void * env_data
Per call environment data.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Temporary structure to hold arguments for module calls.
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.
int fr_pair_append(fr_pair_list_t *list, fr_pair_t *to_add)
Add a VP to the end of the list.
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.
int fr_pair_value_from_str(fr_pair_t *vp, char const *value, size_t inlen, fr_sbuff_unescape_rules_t const *uerules, bool tainted)
Convert string value to native attribute value.
void radius_pairmove(request_t *request, fr_pair_list_t *to, fr_pair_list_t *from)
static rc_request_t * current
#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.
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.
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.
size_t rest_get_handle_data(char const **out, fr_curl_io_request_t *randle)
Extracts pointer to buffer containing response data.
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.
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.
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
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 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.
struct rlm_rest_call_env_t::@161 request
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
struct rlm_rest_call_env_t::@162 response
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.
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.
void * encoder
Encoder specific data.
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)
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.
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.
static fr_dict_attr_t const * tmpl_attr_tail_da(tmpl_t const *vpt)
Return the last attribute reference da.
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.
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_list(tmpl_t const *vpt)
Optional arguments passed to vp_tmpl functions.
static char buff[sizeof("18446744073709551615")+3]
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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.
Functions which we wish were included in the standard talloc distribution.
#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