24RCSID(
"$Id: cddd8da5743b9cfb06439bb242a3e14073fdce0f $")
26#include <freeradius-devel/curl/base.h>
27#include <freeradius-devel/curl/xlat.h>
28#include <freeradius-devel/server/base.h>
29#include <freeradius-devel/server/cf_parse.h>
31#include <freeradius-devel/server/global_lib.h>
32#include <freeradius-devel/server/tmpl.h>
33#include <freeradius-devel/util/atexit.h>
34#include <freeradius-devel/util/debug.h>
35#include <freeradius-devel/util/uri.h>
36#include <freeradius-devel/unlang/call_env.h>
37#include <freeradius-devel/unlang/xlat_func.h>
55 {
L(
"1.0"), CURL_HTTP_VERSION_1_0 },
56 {
L(
"1.1"), CURL_HTTP_VERSION_1_1 },
60#if CURL_AT_LEAST_VERSION(7,49,0)
61 {
L(
"2.0"), CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE },
63#if CURL_AT_LEAST_VERSION(7,33,0)
64 {
L(
"2.0+auto"), CURL_HTTP_VERSION_2_0 },
68#if CURL_AT_LEAST_VERSION(7,47,0)
69 {
L(
"2.0+tls"), CURL_HTTP_VERSION_2TLS },
74 {
L(
"default"), CURL_HTTP_VERSION_NONE }
92 static size_t disable_proxy_table_len =
NUM_ELEMENTS(disable_proxy_table);
103#define SECTION_REQUEST_COMMON \
104 { FR_CONF_OFFSET("body", rlm_rest_section_request_t, body_str), .dflt = "none" }, \
106 { FR_CONF_OFFSET_IS_SET("auth", FR_TYPE_VOID, 0, rlm_rest_section_request_t, auth), \
107 .func = cf_table_parse_int, .uctx = &(cf_table_parse_ctx_t){ .table = http_auth_table, .len = &http_auth_table_len }, .dflt = "none" }, \
108 { FR_CONF_OFFSET("require_auth", rlm_rest_section_request_t, require_auth), .dflt = "no" }, \
109 { FR_CONF_OFFSET("chunk", rlm_rest_section_request_t, chunk), .dflt = "0" } \
163#ifdef CURLPIPE_MULTIPLEX
175#define REST_CALL_ENV_REQUEST_COMMON(_dflt_username, _dflt_password) \
176 { FR_CALL_ENV_OFFSET("header", FR_TYPE_STRING, CALL_ENV_FLAG_MULTI, rlm_rest_call_env_t, request.header) }, \
177 { FR_CALL_ENV_OFFSET("data", FR_TYPE_STRING, CALL_ENV_FLAG_CONCAT, rlm_rest_call_env_t, request.data) }, \
178 { FR_CALL_ENV_OFFSET("username", FR_TYPE_STRING, CALL_ENV_FLAG_SINGLE | CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_BARE_WORD_ATTRIBUTE, \
179 rlm_rest_call_env_t, request.username), .pair.dflt_quote = T_BARE_WORD, _dflt_username }, \
180 { FR_CALL_ENV_OFFSET("password", FR_TYPE_STRING, CALL_ENV_FLAG_SINGLE | CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_SECRET | CALL_ENV_FLAG_BARE_WORD_ATTRIBUTE, \
181 rlm_rest_call_env_t, request.password), .pair.dflt_quote = T_BARE_WORD, _dflt_password }, \
183#define REST_CALL_ENV_RESPONSE_COMMON \
184 { FR_CALL_ENV_PARSE_ONLY_OFFSET("header", FR_TYPE_STRING, CALL_ENV_FLAG_ATTRIBUTE, rlm_rest_call_env_t, response.header) }, \
186#define REST_CALL_ENV_SECTION(_var, _dflt_username, _dflt_password) \
187static const call_env_parser_t _var[] = { \
188 { FR_CALL_ENV_SUBSECTION("request", NULL, CALL_ENV_FLAG_REQUIRED, \
189 ((call_env_parser_t[]) { \
190 { FR_CALL_ENV_OFFSET("uri", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT, rlm_rest_call_env_t, request.uri), \
193 .func = fr_uri_escape, \
194 .safe_for = CURL_URI_SAFE_FOR, \
195 .always_escape = true, \
197 .mode = TMPL_ESCAPE_PRE_CONCAT, \
200 .alloc = rest_uri_part_escape_uctx_alloc, \
201 .uctx = rest_uri_parts \
203 .type = TMPL_ESCAPE_UCTX_ALLOC_FUNC \
206 .pair.literals_safe_for = CURL_URI_SAFE_FOR}, \
207 REST_CALL_ENV_REQUEST_COMMON(_dflt_username, _dflt_password) \
208 CALL_ENV_TERMINATOR \
210 { FR_CALL_ENV_SUBSECTION("response", NULL, CALL_ENV_FLAG_NONE, \
211 ((call_env_parser_t[]) { \
212 REST_CALL_ENV_RESPONSE_COMMON \
213 CALL_ENV_TERMINATOR \
215 CALL_ENV_TERMINATOR \
219REST_CALL_ENV_SECTION(rest_section_authenticate_env, .pair.dflt = "User-Name", .pair.dflt = "User-Password")
232 REST_CALL_ENV_REQUEST_COMMON(,) \
237 REST_CALL_ENV_RESPONSE_COMMON \
238 CALL_ENV_TERMINATOR \
276 return CMP(a->
cs, b->cs);
292 RDEBUG2(
"Updating result attribute(s)");
298 RDEBUG2(
"request.REST-HTTP-Status-Code !* ANY");
303 RDEBUG2(
"request.REST-HTTP-Status-Code := %i", code);
306 vp->vp_uint32 = code;
333 memset(t_ctx, 0,
sizeof(*t_ctx));
335 t_ctx->uri_part = uctx;
352 if (!escaped)
return -1;
357 if (strlen(escaped) == vb->vb_length) {
378 RDEBUG2(
"Sending HTTP %s to \"%pV\"",
386 call_env->
request.uri->vb_strvalue,
387 call_env->
request.data ? call_env->
request.data->vb_strvalue : NULL);
388 if (ret < 0)
return -1;
395 if (ret < 0)
return -1;
439 if ((hcode >= 200) && (hcode < 300)) {
441 }
else if (hcode < 500) {
468 rest_slab_release(handle);
494 fr_value_box_list_t *
in)
512 XLAT_ARGS(
in, &method_vb, &uri_vb, &data_vb, &header_vb);
520 memcpy(&rctx->
section, &
inst->xlat,
sizeof(*section));
561 randle = rctx->
handle = rest_slab_reserve(t->
slab);
567 RDEBUG2(
"Sending HTTP %s to \"%pV\"",
576 rest_slab_release(randle);
591 uri_vb->vb_strvalue, data_vb ? data_vb->vb_strvalue : NULL);
592 if (ret < 0)
goto error_release;
601 if (ret < 0)
goto error_release;
656 if ((hcode >= 200) && (hcode < 300)) {
662 }
else if (hcode < 500) {
682 rest_slab_release(handle);
702 handle = rest_slab_reserve(t->
slab);
707 rest_slab_release(handle);
766 if ((hcode >= 200) && (hcode < 300)) {
772 }
else if (hcode < 500) {
792 rest_slab_release(handle);
812 if (!call_env->
request.username) {
813 REDEBUG(
"Attribute \"User-Name\" is required for authentication");
817 if (!call_env->
request.password) {
818 REDEBUG(
"Attribute \"User-Password\" is required for authentication");
825 if (call_env->
request.password->vb_length == 0) {
826 REDEBUG(
"User-Password must not be empty");
834 RDEBUG(
"Login attempt with password \"%pV\"", call_env->
request.password);
836 RDEBUG2(
"Login attempt with password");
839 handle = rest_slab_reserve(t->
slab);
844 rest_slab_release(handle);
873 }
else if (hcode == 204) {
875 }
else if ((hcode >= 200) && (hcode < 300)) {
896 rest_slab_release(handle);
912 handle = rest_slab_reserve(t->
slab);
917 rest_slab_release(handle);
951 cf_log_err(cs,
"Unsupported HTTP auth type \"%s\", check libcurl version, OpenSSL build "
952 "configuration, then recompile this module",
996 cf_log_err(cs,
"Unsupported HTTP body type \"%s\", please submit patches",
997 config->request.body_str);
1001 cf_log_err(cs,
"Invalid HTTP body type. \"%s\" is not a valid web API data "
1002 "markup format",
config->request.body_str);
1006 cf_log_err(cs,
"Unavailable HTTP body type. \"%s\" is not available in this "
1007 "build",
config->request.body_str);
1015 if (
config->response.force_to_str) {
1022 cf_log_err(cs,
"Unknown forced response body type '%s'",
config->response.force_to_str);
1028 cf_log_err(cs,
"Unsupported forced response body type \"%s\", please submit patches",
1029 config->response.force_to_str);
1033 cf_log_err(cs,
"Invalid HTTP forced response body type. \"%s\" is not a valid web API data "
1034 "markup format",
config->response.force_to_str);
1056 CURL *candle = randle->
candle;
1061 curl_easy_reset(candle);
1067 curl_slist_free_all(ctx->
headers);
1079 ret = curl_easy_setopt(candle, CURLOPT_PRIVATE, (
void *)0xdeadc341);
1081 ERROR(
"Failed to set private data on curl easy handle %p: %s",
1082 candle, curl_easy_strerror(ret));
1090 TALLOC_FREE(ctx->
body);
1102 curl_easy_cleanup(randle->
candle);
1111 randle->
candle = curl_easy_init();
1122 randle->
uctx = curl_ctx;
1148 if (!(t->
slab = rest_slab_list_alloc(t, mctx->
el, &
inst->conn_config.reuse,
1150 ERROR(
"Connection handle pool instantiation failed");
1155 if (!mhandle)
return -1;
1197 inst->xlat.request.method_str =
"GET";
1199 inst->xlat.request.body_str =
"application/x-www-form-urlencoded";
1200 inst->xlat.response.force_to_str =
"plain";
1219 inst->conn_config.reuse.num_children = 1;
1262 char *p, *name2 = NULL;
1272 name2 = talloc_strdup(NULL, cec->
asked->
name2);
1274 for (i = 0; i < talloc_array_length(name2); i++) {
1285 if (!
inst->sections_init) {
1287 inst->sections_init =
true;
1291 cf_log_err(cs,
"%s called in %s %s - requires conf section %s %s%s%s", cec->
mi->
name,
1304 if (strcmp(cec->
asked->
name1,
"authenticate") == 0) {
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
#define fr_atexit_thread_local(_name, _free, _uctx)
#define L(_str)
Helper for initialising arrays of string literals.
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
int call_env_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *parsed, char const *name, tmpl_rules_t const *t_rules, CONF_SECTION const *cs, call_env_ctx_t const *cec, call_env_parser_t const *rule)
Parse per call env.
call_env_parsed_t * call_env_parsed_add(TALLOC_CTX *ctx, call_env_parsed_head_t *head, call_env_parser_t const *rule)
Allocate a new call_env_parsed_t structure and add it to the list of parsed call envs.
void call_env_parsed_set_data(call_env_parsed_t *parsed, void const *data)
Assign data to a call_env_parsed_t.
#define CALL_ENV_TERMINATOR
#define FR_CALL_ENV_METHOD_OUT(_inst)
Helper macro for populating the size/type fields of a call_env_method_t from the output structure typ...
call_env_parser_t const * env
Parsing rules for call method env.
section_name_t const * asked
The actual name1/name2 that resolved to a module_method_binding_t.
#define FR_CALL_ENV_SUBSECTION(_name, _name2, _flags, _subcs)
Specify a call_env_parser_t which defines a nested subsection.
@ CALL_ENV_FLAG_PARSE_ONLY
The result of parsing will not be evaluated at runtime.
@ CALL_ENV_FLAG_PARSE_MISSING
If this subsection is missing, still parse it.
@ CALL_ENV_PARSE_TYPE_VOID
Output of the parsing phase is undefined (a custom structure).
module_instance_t const * mi
Module instance that the callenv is registered to.
#define FR_CALL_ENV_SUBSECTION_FUNC(_name, _name2, _flags, _func)
Specify a call_env_parser_t which parses a subsection using a callback function.
int cf_section_parse(TALLOC_CTX *ctx, void *base, CONF_SECTION *cs)
Parse a configuration section into user-supplied variables.
int cf_table_parse_int(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, conf_parser_t const *rule)
Generic function for parsing conf pair values as int.
#define CONF_PARSER_TERMINATOR
cf_parse_t func
Override default parsing behaviour for the specified type with a custom parsing function.
#define FR_CONF_DEPRECATED(_name, _struct, _field)
conf_parser_t entry which raises an error if a matching CONF_PAIR is found
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
#define cf_section_rules_push(_cs, _rule)
#define FR_CONF_OFFSET_SUBSECTION(_name, _flags, _struct, _field, _subcs)
conf_parser_t which populates a sub-struct using a CONF_SECTION
#define FR_CONF_OFFSET_TYPE_FLAGS(_name, _type, _flags, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
Common header for all CONF_* types.
A section grouping multiple CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
CONF_SECTION * cf_item_to_section(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_SECTION.
CONF_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
char const * cf_section_name(CONF_SECTION const *cs)
Return name2 if set, else name1.
CONF_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a CONF_PAIR.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
fr_curl_handle_t * fr_curl_io_init(TALLOC_CTX *ctx, fr_event_list_t *el, bool multiplex)
request_t * request
Current request.
void * uctx
Private data for the module using the API.
int fr_curl_io_request_enqueue(fr_curl_handle_t *mhandle, request_t *request, fr_curl_io_request_t *creq)
Sends a request using libcurl.
CURL * candle
Request specific handle.
Uctx data for timer and I/O functions.
Structure representing an individual request being passed to curl for processing.
#define CURL_URI_SAFE_FOR
safe for value suitable for all users of the curl library
static int fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
Insert directly after the current item.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
#define GLOBAL_LIB_TERMINATOR
Structure to define how to initialise libraries with global configuration.
static xlat_action_t rest_xlat(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, fr_value_box_list_t *in)
Simple xlat to read text data from a URL.
void fr_json_version_print(void)
Print JSON-C version.
int fr_curl_response_certinfo(request_t *request, fr_curl_io_request_t *randle)
global_lib_autoinst_t fr_curl_autoinst
CURL * fr_curl_tmp_handle(void)
Return a thread local curl easy handle.
conf_parser_t fr_curl_conn_config[]
conf_parser_t fr_curl_tls_config[]
#define REXDENT()
Exdent (unindent) R* messages by one level.
#define RDEBUG_ENABLED3
True if request debug level 1-3 messages are enabled.
#define RPEDEBUG(fmt,...)
#define RINDENT()
Indent R* messages by one level.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
void * env_data
Per call environment data.
module_instance_t const * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
void * rctx
Resume ctx that a module previously set.
fr_event_list_t * el
Event list to register any IO handlers and timers against.
void * thread
Thread instance data.
module_instance_t const * mi
Instance of the module being instantiated.
#define MODULE_CTX(_mi, _thread, _env_data, _rctx)
Wrapper to create a module_ctx_t as a compound literal.
module_instance_t * mi
Instance of the module being instantiated.
Temporary structure to hold arguments for module calls.
Temporary structure to hold arguments for instantiation calls.
Temporary structure to hold arguments for thread_instantiation calls.
xlat_t * module_rlm_xlat_register(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
module_t common
Common fields presented by all modules.
void rest_io_module_signal(module_ctx_t const *mctx, request_t *request, UNUSED fr_signal_t action)
Handle asynchronous cancellation of a request.
void rest_io_xlat_signal(xlat_ctx_t const *xctx, request_t *request, fr_signal_t action)
Handle asynchronous cancellation of a request.
static const conf_parser_t config[]
#define pair_update_request(_attr, _da)
void * fr_rb_iter_init_inorder(fr_rb_iter_inorder_t *iter, fr_rb_tree_t *tree)
Initialise an in-order iterator.
int fr_rb_find_or_insert(void **found, fr_rb_tree_t *tree, void const *data)
Attempt to find current data in the tree, if it does not exist insert it.
void * fr_rb_iter_next_inorder(fr_rb_iter_inorder_t *iter)
Return the next node.
#define fr_rb_inline_init(_tree, _type, _field, _data_cmp, _data_free)
Initialises a red black tree.
Iterator structure for in-order traversal of an rbtree.
#define RETURN_UNLANG_INVALID
#define RETURN_UNLANG_RCODE(_rcode)
#define RETURN_UNLANG_FAIL
rlm_rcode_t
Return codes indicating the result of the module call.
@ RLM_MODULE_INVALID
The module considers the request invalid.
@ RLM_MODULE_OK
The module is OK, continue.
@ RLM_MODULE_FAIL
Module failed, don't reply.
@ RLM_MODULE_DISALLOW
Reject the request (user is locked out).
@ RLM_MODULE_REJECT
Immediately reject the request.
@ RLM_MODULE_NOTFOUND
User not found.
@ RLM_MODULE_UPDATED
OK (pairs modified).
fr_table_num_sorted_t const http_auth_table[]
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.
fr_table_num_sorted_t const http_body_type_table[]
Conversion table for type config values.
fr_table_num_sorted_t const http_method_table[]
Conversion table for method config values.
size_t rest_get_handle_data(char const **out, fr_curl_io_request_t *randle)
Extracts pointer to buffer containing response data.
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.
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.
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.
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.
Function prototypes and datatypes for the REST (HTTP) transport.
rlm_rest_t const * instance
This instance of rlm_rest.
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.
#define rest_get_handle_code(_handle)
char * buffer
Raw incoming HTTP data.
fr_curl_handle_t * mhandle
Thread specific multi handle.
char * body
Pointer to the buffer which contains body data/ Only used when not performing chunked encoding.
@ REST_HTTP_METHOD_UNKNOWN
@ REST_HTTP_METHOD_CUSTOM
Must always come last, should not be in method table.
@ REST_HTTP_BODY_UNSUPPORTED
@ REST_HTTP_BODY_NUM_ENTRIES
@ REST_HTTP_BODY_UNAVAILABLE
char const * method_str
The string version of the HTTP method.
struct rlm_rest_call_env_t::@186 request
rlm_rest_section_t section
Parsed section config.
rlm_rest_section_conf_t * section
Section config.
rlm_rest_section_request_t request
Request configuration.
rlm_rest_response_t response
Response context data.
void * decoder
Decoder specific data.
void * encoder
Encoder specific data.
rlm_rest_request_t request
Request context data.
http_method_t method
What HTTP method should be used, GET, POST etc...
rlm_rest_section_t section
Our mutated section config.
rlm_rest_t const * inst
Instance of rlm_rest.
rest_slab_list_t * slab
Slab list for connection handles.
http_body_type_t body
What encoding type should be used.
fr_curl_io_request_t * handle
curl easy handle servicing our request.
rlm_rest_t const * instance
This instance of rlm_rest.
CONF_SECTION * cs
Conf section found for this call.
Thread specific rlm_rest instance data.
Stores the state of a yielded xlat.
static const call_env_method_t rest_call_env_xlat
static int rlm_rest_status_update(request_t *request, void *handle)
Update the status attribute.
static int mod_load(void)
static int8_t rest_section_cmp(void const *one, void const *two)
static int rest_conn_alloc(fr_curl_io_request_t *randle, void *uctx)
static int _rest_uri_part_escape_uctx_free(void *uctx)
static const conf_parser_t xlat_config[]
static xlat_action_t rest_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
static int parse_sub_section(rlm_rest_t *inst, CONF_SECTION *parent, conf_parser_t const *config_items, rlm_rest_section_t *config, char const *name, CONF_SECTION *cs)
static unlang_action_t mod_common(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
fr_dict_t const * dict_freeradius
static int rlm_rest_perform(module_ctx_t const *mctx, rlm_rest_section_t const *section, fr_curl_io_request_t *randle, request_t *request)
static const conf_parser_t xlat_request_config[]
static fr_table_num_sorted_t const http_negotiation_table[]
static fr_uri_part_t const rest_uri_parts[]
static int mod_bootstrap(module_inst_ctx_t const *mctx)
fr_dict_attr_t const * attr_rest_http_header
static unlang_action_t mod_accounting(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
fr_dict_autoload_t rlm_rest_dict[]
static const conf_parser_t section_request_config[]
static const conf_parser_t section_config[]
static int _rest_request_cleanup(fr_curl_io_request_t *randle, UNUSED void *uctx)
Cleans up after a REST request.
#define SECTION_REQUEST_COMMON
static int rest_uri_part_escape(fr_value_box_t *vb, void *uctx)
static int rest_proxy_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
static const call_env_method_t rest_method_env
fr_dict_attr_t const * attr_rest_http_status_code
static unlang_action_t mod_accounting_result(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static size_t http_negotiation_table_len
static int mod_thread_instantiate(module_thread_inst_ctx_t const *mctx)
Create a thread specific multihandle.
static unlang_action_t mod_authenticate(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
fr_dict_attr_t const * attr_rest_http_body
fr_dict_attr_autoload_t rlm_rest_dict_attr[]
static const conf_parser_t section_response_config[]
#define REST_CALL_ENV_SECTION(_var, _dflt_username, _dflt_password)
static const conf_parser_t module_config[]
static int _mod_conn_free(fr_curl_io_request_t *randle)
static xlat_arg_parser_t const rest_xlat_args[]
static unlang_action_t mod_authenticate_result(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
Cleanup all outstanding requests associated with this thread.
static int mod_instantiate(module_inst_ctx_t const *mctx)
static unlang_action_t mod_common_result(unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static void * rest_uri_part_escape_uctx_alloc(UNUSED request_t *request, void const *uctx)
Allocate an escape uctx to pass to fr_uri_escape.
global_lib_autoinst_t const *const rlm_rest_lib[]
char const * rest_no_proxy
Unique pointer used to determine if we should explicitly disable proxying.
static int rest_sect_parse(TALLOC_CTX *ctx, call_env_parsed_head_t *out, UNUSED tmpl_rules_t const *t_rules, CONF_ITEM *ci, call_env_ctx_t const *cec, UNUSED call_env_parser_t const *rule)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
#define SECTION_NAME(_name1, _name2)
Define a section name consisting of a verb and a noun.
char const * name2
Second section name. Usually a packet type like 'access-request', 'access-accept',...
char const * name1
First section name. Usually a verb like 'recv', 'send', etc...
char const * name
Instance name e.g. user_database.
CONF_SECTION * conf
Module's instance configuration.
size_t inst_size
Size of the module's instance data.
void * data
Module's instance data.
void * boot
Data allocated during the boostrap phase.
#define MODULE_BINDING_TERMINATOR
Terminate a module binding list.
Named methods exported by a module.
#define pair_delete_request(_pair_or_da)
Delete a fr_pair_t in the request list.
Optional arguments passed to vp_tmpl functions.
@ FR_SIGNAL_CANCEL
Request has been cancelled.
unlang_action_t unlang_module_yield(request_t *request, module_method_t resume, unlang_module_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
eap_aka_sim_process_conf_t * inst
Stores an attribute, a value and various bits of other data.
#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_bstrndup(TALLOC_CTX *ctx, char const *in, size_t inlen)
Binary safe strndup function.
char * talloc_typed_strdup(TALLOC_CTX *ctx, char const *p)
Call talloc_strdup, setting the type on the new chunk correctly.
#define talloc_get_type_abort_const
xlat_action_t unlang_xlat_yield(request_t *request, xlat_func_t resume, xlat_func_signal_t signal, fr_signal_t sigmask, void *rctx)
Yield a request back to the interpreter from within a module.
uint8_t required
Argument must be present, and non-empty.
#define XLAT_ARGS(_list,...)
Populate local variables with value boxes from the input list.
#define XLAT_ARG_PARSER_TERMINATOR
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
Definition for a single argument consumend by an xlat function.
int fr_uri_escape_list(fr_value_box_list_t *uri, fr_uri_part_t const *uri_parts, void *uctx)
Parse a list of value boxes representing a URI.
#define XLAT_URI_PART_TERMINATOR
char const * name
Name of this part of the URI.
uctx to pass to fr_uri_escape
Definition for a single part of a URI.
#define fr_strerror_printf(_fmt,...)
Log to thread local error buffer.
void fr_value_box_strdup_shallow_replace(fr_value_box_t *vb, char const *src, ssize_t len)
Free the existing buffer (if talloced) associated with the valuebox, and replace it with a new one.
int fr_value_box_bstrndup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, size_t len, bool tainted)
Copy a string to to a fr_value_box_t.
int fr_value_box_list_concat_in_place(TALLOC_CTX *ctx, fr_value_box_t *out, fr_value_box_list_t *list, fr_type_t type, fr_value_box_list_action_t proc_action, bool flatten, size_t max_size)
Concatenate a list of value boxes.
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
#define fr_value_box_list_foreach(_list_head, _iter)
static size_t char ** out
void * rctx
Resume context.
void * env_data
Expanded call env data.
module_ctx_t const * mctx
Synthesised module calling ctx.
int xlat_func_args_set(xlat_t *x, xlat_arg_parser_t const args[])
Register the arguments of an xlat.
void xlat_func_call_env_set(xlat_t *x, call_env_method_t const *env_method)
Register call environment of an xlat.