26 RCSID(
"$Id: 7dbe316f97d44d8a301a68d8bc7dc7e6ff0bbb75 $")
28 #include <freeradius-devel/curl/base.h>
29 #include <freeradius-devel/curl/xlat.h>
30 #include <freeradius-devel/server/base.h>
31 #include <freeradius-devel/server/cf_parse.h>
32 #include <freeradius-devel/server/cf_util.h>
34 #include <freeradius-devel/server/global_lib.h>
35 #include <freeradius-devel/server/module_rlm.h>
36 #include <freeradius-devel/server/tmpl.h>
37 #include <freeradius-devel/server/tmpl_escape.h>
38 #include <freeradius-devel/server/pairmove.h>
39 #include <freeradius-devel/server/log.h>
40 #include <freeradius-devel/tls/base.h>
41 #include <freeradius-devel/util/atexit.h>
42 #include <freeradius-devel/util/debug.h>
43 #include <freeradius-devel/util/table.h>
44 #include <freeradius-devel/util/uri.h>
45 #include <freeradius-devel/util/value.h>
46 #include <freeradius-devel/unlang/call_env.h>
47 #include <freeradius-devel/unlang/xlat_func.h>
48 #include <freeradius-devel/unlang/xlat.h>
66 {
L(
"1.0"), CURL_HTTP_VERSION_1_0 },
67 {
L(
"1.1"), CURL_HTTP_VERSION_1_1 },
71 #if CURL_AT_LEAST_VERSION(7,49,0)
72 {
L(
"2.0"), CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE },
74 #if CURL_AT_LEAST_VERSION(7,33,0)
75 {
L(
"2.0+auto"), CURL_HTTP_VERSION_2_0 },
79 #if CURL_AT_LEAST_VERSION(7,47,0)
80 {
L(
"2.0+tls"), CURL_HTTP_VERSION_2TLS },
85 {
L(
"default"), CURL_HTTP_VERSION_NONE }
103 static size_t disable_proxy_table_len =
NUM_ELEMENTS(disable_proxy_table);
114 #define SECTION_REQUEST_COMMON \
115 { FR_CONF_OFFSET("body", rlm_rest_section_request_t, body_str), .dflt = "none" }, \
117 { FR_CONF_OFFSET_IS_SET("auth", FR_TYPE_VOID, 0, rlm_rest_section_request_t, auth), \
118 .func = cf_table_parse_int, .uctx = &(cf_table_parse_ctx_t){ .table = http_auth_table, .len = &http_auth_table_len }, .dflt = "none" }, \
119 { FR_CONF_OFFSET("require_auth", rlm_rest_section_request_t, require_auth), .dflt = "no" }, \
120 { FR_CONF_OFFSET("chunk", rlm_rest_section_request_t, chunk), .dflt = "0" } \
174 #ifdef CURLPIPE_MULTIPLEX
186 #define REST_CALL_ENV_REQUEST_COMMON(_dflt_username, _dflt_password) \
187 { FR_CALL_ENV_OFFSET("header", FR_TYPE_STRING, CALL_ENV_FLAG_MULTI, rlm_rest_call_env_t, request.header) }, \
188 { FR_CALL_ENV_OFFSET("data", FR_TYPE_STRING, CALL_ENV_FLAG_CONCAT, rlm_rest_call_env_t, request.data) }, \
189 { FR_CALL_ENV_OFFSET("username", FR_TYPE_STRING, CALL_ENV_FLAG_SINGLE | CALL_ENV_FLAG_NULLABLE, \
190 rlm_rest_call_env_t, request.username), .pair.dflt_quote = T_BARE_WORD, _dflt_username }, \
191 { FR_CALL_ENV_OFFSET("password", FR_TYPE_STRING, CALL_ENV_FLAG_SINGLE | CALL_ENV_FLAG_NULLABLE | CALL_ENV_FLAG_SECRET, \
192 rlm_rest_call_env_t, request.password), .pair.dflt_quote = T_BARE_WORD, _dflt_password }, \
194 #define REST_CALL_ENV_RESPONSE_COMMON \
195 { FR_CALL_ENV_PARSE_ONLY_OFFSET("header", FR_TYPE_STRING, CALL_ENV_FLAG_ATTRIBUTE, rlm_rest_call_env_t, response.header) }, \
197 #define REST_CALL_ENV_SECTION(_var, _section, _dflt_username, _dflt_password) \
198 static const call_env_method_t _var = { \
199 FR_CALL_ENV_METHOD_OUT(rlm_rest_call_env_t), \
200 .env = (call_env_parser_t[]){ \
201 { FR_CALL_ENV_SUBSECTION(_section, NULL, CALL_ENV_FLAG_NONE, \
202 ((call_env_parser_t[]) { \
203 { FR_CALL_ENV_SUBSECTION("request", NULL, CALL_ENV_FLAG_NONE, \
204 ((call_env_parser_t[]) { \
205 { FR_CALL_ENV_OFFSET("uri", FR_TYPE_STRING, CALL_ENV_FLAG_REQUIRED | CALL_ENV_FLAG_CONCAT, rlm_rest_call_env_t, request.uri), \
207 .func = fr_uri_escape, \
208 .mode = TMPL_ESCAPE_PRE_CONCAT, \
211 .alloc = rest_uri_part_escape_uctx_alloc, \
212 .uctx = rest_uri_parts \
214 .type = TMPL_ESCAPE_UCTX_ALLOC_FUNC\
216 .safe_for = CURL_URI_SAFE_FOR \
218 .pair.literals_safe_for = CURL_URI_SAFE_FOR},
\
219 REST_CALL_ENV_REQUEST_COMMON(_dflt_username, _dflt_password) \
220 CALL_ENV_TERMINATOR \
222 { FR_CALL_ENV_SUBSECTION("response", NULL, CALL_ENV_FLAG_NONE, \
223 ((call_env_parser_t[]) { \
224 REST_CALL_ENV_RESPONSE_COMMON \
225 CALL_ENV_TERMINATOR \
227 CALL_ENV_TERMINATOR \
230 CALL_ENV_TERMINATOR \
235 REST_CALL_ENV_SECTION(rest_call_env_authenticate,
"authenticate", .pair.dflt =
"&User-Name", .pair.dflt =
"&User-Password");
254 REST_CALL_ENV_REQUEST_COMMON(,) \
255 CALL_ENV_TERMINATOR \
259 REST_CALL_ENV_RESPONSE_COMMON \
260 CALL_ENV_TERMINATOR \
262 CALL_ENV_TERMINATOR \
265 CALL_ENV_TERMINATOR \
314 RDEBUG2(
"Updating result attribute(s)");
320 RDEBUG2(
"&request.REST-HTTP-Status-Code !* ANY");
325 RDEBUG2(
"&request.REST-HTTP-Status-Code := %i", code);
328 vp->vp_uint32 = code;
355 memset(t_ctx, 0,
sizeof(*t_ctx));
357 t_ctx->uri_part = uctx;
374 if (!escaped)
return -1;
379 if (strlen(escaped) == vb->vb_length) {
400 RDEBUG2(
"Sending HTTP %s to \"%pV\"",
408 call_env->
request.uri->vb_strvalue,
409 call_env->
request.data ? call_env->
request.data->vb_strvalue : NULL);
410 if (ret < 0)
return -1;
417 if (ret < 0)
return -1;
461 if ((hcode >= 200) && (hcode < 300)) {
463 }
else if (hcode < 500) {
490 rest_slab_release(handle);
514 fr_value_box_list_t *
in)
534 memcpy(&rctx->
section, &
inst->xlat,
sizeof(*section));
541 if ((fr_value_box_list_head(
in))) {
542 uri_vb = fr_value_box_list_head(&in_vb->vb_group);
547 REDEBUG(
"Failed concatenating argument");
564 in_vb = fr_value_box_list_pop_head(
in);
573 randle = rctx->
handle = rest_slab_reserve(t->
slab);
590 rest_slab_release(randle);
596 uri_vb = fr_value_box_list_head(&in_vb->vb_group);
608 if ((in_vb = fr_value_box_list_head(
in))) {
613 REDEBUG(
"Failed to concatenate freeform data");
619 RDEBUG2(
"Sending HTTP %s to \"%pV\"",
633 uri_vb->vb_strvalue, in_vb ? in_vb->vb_strvalue : NULL);
634 if (ret < 0)
goto error;
643 if (ret < 0)
goto error;
697 if ((hcode >= 200) && (hcode < 300)) {
703 }
else if (hcode < 500) {
723 rest_slab_release(handle);
743 if (!section->
name) {
744 RDEBUG2(
"No authorize section configured");
748 handle = rest_slab_reserve(t->
slab);
753 rest_slab_release(handle);
811 if ((hcode >= 200) && (hcode < 300)) {
817 }
else if (hcode < 500) {
837 rest_slab_release(handle);
855 if (!section->
name) {
856 RDEBUG2(
"No authentication section configured");
864 if (!call_env->
request.username) {
865 REDEBUG(
"Attribute \"User-Name\" is required for authentication");
869 if (!call_env->
request.password) {
870 REDEBUG(
"Attribute \"User-Password\" is required for authentication");
877 if (call_env->
request.password->vb_length == 0) {
878 REDEBUG(
"User-Password must not be empty");
886 RDEBUG(
"Login attempt with password \"%pV\"", &call_env->
request.password);
888 RDEBUG2(
"Login attempt with password");
891 handle = rest_slab_reserve(t->
slab);
896 rest_slab_release(handle);
924 }
else if (hcode == 204) {
926 }
else if ((hcode >= 200) && (hcode < 300)) {
947 rest_slab_release(handle);
964 if (!section->
name) {
965 RDEBUG2(
"No accounting section configured");
969 handle = rest_slab_reserve(t->
slab);
974 rest_slab_release(handle);
1002 }
else if (hcode == 204) {
1004 }
else if ((hcode >= 200) && (hcode < 300)) {
1025 rest_slab_release(handle);
1042 if (!section->
name) {
1043 RDEBUG2(
"No post-auth section configured");
1047 handle = rest_slab_reserve(t->
slab);
1052 rest_slab_release(handle);
1086 cf_log_err(cs,
"Unsupported HTTP auth type \"%s\", check libcurl version, OpenSSL build "
1087 "configuration, then recompile this module",
1131 cf_log_err(cs,
"Unsupported HTTP body type \"%s\", please submit patches",
1132 config->request.body_str);
1136 cf_log_err(cs,
"Invalid HTTP body type. \"%s\" is not a valid web API data "
1137 "markup format",
config->request.body_str);
1141 cf_log_err(cs,
"Unavailable HTTP body type. \"%s\" is not available in this "
1142 "build",
config->request.body_str);
1150 if (
config->response.force_to_str) {
1157 cf_log_err(cs,
"Unknown forced response body type '%s'",
config->response.force_to_str);
1163 cf_log_err(cs,
"Unsupported forced response body type \"%s\", please submit patches",
1164 config->response.force_to_str);
1168 cf_log_err(cs,
"Invalid HTTP forced response body type. \"%s\" is not a valid web API data "
1169 "markup format",
config->response.force_to_str);
1182 curl_easy_cleanup(randle->
candle);
1200 CURL *candle = randle->
candle;
1205 curl_easy_reset(candle);
1211 curl_slist_free_all(ctx->
headers);
1218 TALLOC_FREE(ctx->
body);
1233 randle->
candle = curl_easy_init();
1244 randle->
uctx = curl_ctx;
1270 if (!(t->
slab = rest_slab_list_alloc(t, mctx->
el, &
inst->conn_config.reuse,
1272 ERROR(
"Connection handle pool instantiation failed");
1277 if (!mhandle)
return -1;
1317 inst->xlat.request.method_str =
"GET";
1319 inst->xlat.request.body_str =
"application/x-www-form-urlencoded";
1320 inst->xlat.response.force_to_str =
"plain";
1339 inst->conn_config.reuse.num_children = 1;
1412 { .name1 =
"recv", .name2 =
"accounting-request", .method =
mod_accounting, .method_env = &rest_call_env_accounting },
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.
call_env_parser_t const * env
Parsing rules for call method env.
#define FR_CALL_ENV_SUBSECTION(_name, _ident2, _flags, _subcs)
Specify a call_env_parser_t which defines a nested subsection.
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
#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_PAIR * cf_item_to_pair(CONF_ITEM const *ci)
Cast a CONF_ITEM to a 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_PAIR * cf_pair_find(CONF_SECTION const *cs, char const *attr)
Search for a CONF_PAIR with a specific name.
char const * cf_pair_value(CONF_PAIR const *pair)
Return the value of a CONF_PAIR.
#define cf_log_err(_cf, _fmt,...)
@ MOD_POST_AUTH
7 methods index for postauth section.
@ MOD_AUTHORIZE
1 methods index for authorize section.
@ MOD_ACCOUNTING
3 methods index for accounting section.
@ MOD_AUTHENTICATE
0 methods index for authenticate section.
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.
static fr_time_delta_t timeout
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.
dl_module_inst_t const * dl_module_instance_by_data(void const *data)
Lookup a dl_module_inst_t via instance data.
void *_CONST data
Module instance's parsed configuration.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
CONF_SECTION *_CONST conf
Module's instance configuration.
#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
conf_parser_t fr_curl_conn_config[]
CURL * fr_curl_tmp_handle(void)
Return a thread local curl easy handle.
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.
@ FR_TYPE_GROUP
A grouping of other attributes.
void * env_data
Per call environment data.
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.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
void * thread
Thread instance data.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
#define MODULE_CTX(_dl_inst, _thread, _env_data, _rctx)
Wrapper to create a module_ctx_t as a compound literal.
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.
Specifies a module method identifier.
char const * section_type_value[MOD_COUNT]
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)
#define RETURN_MODULE_NOOP
#define RETURN_MODULE_RCODE(_rcode)
#define RETURN_MODULE_INVALID
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.
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.
struct rlm_rest_call_env_t::@161 request
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.
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.
char const * name
Section name.
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.
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)
Initialises libcurl.
static fr_dict_attr_t const * attr_user_password
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)
fr_dict_t const * dict_freeradius
static int rest_request_cleanup(fr_curl_io_request_t *randle, UNUSED void *uctx)
Cleans up after a REST request.
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 unlang_action_t mod_post_auth_result(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static const conf_parser_t xlat_request_config[]
static fr_dict_t const * dict_radius
static fr_table_num_sorted_t const http_negotiation_table[]
static int instantiate(module_inst_ctx_t const *mctx)
static fr_uri_part_t const rest_uri_parts[]
static unlang_action_t mod_authenticate(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static int mod_bootstrap(module_inst_ctx_t const *mctx)
fr_dict_attr_t const * attr_rest_http_header
fr_dict_autoload_t rlm_rest_dict[]
static const conf_parser_t section_request_config[]
static const conf_parser_t section_config[]
#define SECTION_REQUEST_COMMON
static int rest_uri_part_escape(fr_value_box_t *vb, void *uctx)
#define REST_CALL_ENV_SECTION(_var, _section, _dflt_username, _dflt_password)
static int rest_proxy_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED void *parent, CONF_ITEM *ci, UNUSED conf_parser_t const *rule)
fr_dict_attr_t const * attr_rest_http_status_code
static unlang_action_t mod_accounting(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static unlang_action_t mod_authorize(rlm_rcode_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.
fr_dict_attr_t const * attr_rest_http_body
static unlang_action_t mod_authenticate_result(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static fr_dict_attr_t const * attr_user_name
static unlang_action_t mod_accounting_result(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
fr_dict_attr_autoload_t rlm_rest_dict_attr[]
static const conf_parser_t section_response_config[]
static unlang_action_t mod_authorize_result(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
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 int mod_thread_detach(module_thread_inst_ctx_t const *mctx)
Cleanup all outstanding requests associated with this thread.
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)
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 unlang_action_t mod_post_auth(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
#define FR_SBUFF_TERMS(...)
Initialise a terminal structure with a list of sorted strings.
@ MODULE_TYPE_THREAD_SAFE
Module is threadsafe.
#define MODULE_NAME_TERMINATOR
#define pair_delete_request(_pair_or_da)
Delete a fr_pair_t in the request list.
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.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
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.
Functions which we wish were included in the standard talloc distribution.
#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.
bool required
Argument must be present, and non-empty.
@ XLAT_ARG_VARIADIC_EMPTY_KEEP
Empty argument groups are left alone, and either passed through as empty groups or null boxes.
#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_clear_value(fr_value_box_t *data)
Clear/free any existing value.
int fr_value_box_strdup(TALLOC_CTX *ctx, fr_value_box_t *dst, fr_dict_attr_t const *enumv, char const *src, bool tainted)
Copy a nul terminated string to a fr_value_box_t.
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.
static size_t char ** out
void * rctx
Resume context.
module_ctx_t const * mctx
Synthesised module calling ctx.
void * env_data
Expanded call env data.
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.
xlat_t * xlat_func_register_module(TALLOC_CTX *ctx, module_inst_ctx_t const *mctx, char const *name, xlat_func_t func, fr_type_t return_type)
Register an xlat function for a module.